BCF2 optimizations

-- BCF2Type enum has an overloaded method to read the type as an int from an input stream.  This gets rid of a case statement and replaces it with just minimum tiny methods that should be better optimized.  As side effect of this optimization is an overall cleaner code organization
This commit is contained in:
Mark DePristo 2012-08-09 11:09:09 -04:00
parent 9a0dda71d4
commit c6bd9b15ff
4 changed files with 103 additions and 33 deletions

View File

@ -151,7 +151,7 @@ public final class BCF2Codec implements FeatureCodec<VariantContext> {
logger.info("BCF version " + bcfVersion);
final int headerSizeInBytes = BCF2Utils.readInt(BCF2Type.INT32.getSizeInBytes(), inputStream);
final int headerSizeInBytes = BCF2Type.INT32.read(inputStream);
if ( headerSizeInBytes <= 0 || headerSizeInBytes > MAX_HEADER_SIZE) // no bigger than 8 MB
error("BCF2 header has invalid length: " + headerSizeInBytes + " must be >= 0 and < "+ MAX_HEADER_SIZE);

View File

@ -236,7 +236,7 @@ public final class BCF2Decoder {
@Requires("type != null")
public final int decodeInt(final BCF2Type type) throws IOException {
return BCF2Utils.readInt(type.getSizeInBytes(), recordStream);
return type.read(recordStream);
}
/**
@ -312,7 +312,7 @@ public final class BCF2Decoder {
* @return
*/
public final int readBlockSize(final InputStream inputStream) throws IOException {
return BCF2Utils.readInt(4, inputStream);
return BCF2Type.INT32.read(inputStream);
}
/**

View File

@ -26,6 +26,9 @@ package org.broadinstitute.sting.utils.codecs.bcf2;
import com.google.java.contract.Requires;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.EnumSet;
/**
@ -35,12 +38,82 @@ import java.util.EnumSet;
* @since 05/12
*/
public enum BCF2Type {
MISSING(0, 0, 0x00),
INT8 (1, 1, 0xFFFFFF80, -127, 127), // todo -- confirm range
INT16(2, 2, 0xFFFF8000, -32767, 32767),
INT32(3, 4, 0x80000000, -2147483647, 2147483647),
FLOAT(5, 4, 0x7F800001),
CHAR (7, 1, 0x00000000);
// the actual values themselves
MISSING(0, 0, 0x00) {
@Override public int read(final InputStream in) throws IOException {
throw new IllegalArgumentException("Cannot read MISSING type");
}
@Override public void write(final int value, final OutputStream out) throws IOException {
throw new IllegalArgumentException("Cannot write MISSING type");
}
},
// todo -- confirm range
INT8 (1, 1, 0xFFFFFF80, -127, 127) {
@Override
public int read(final InputStream in) throws IOException {
return BCF2Utils.readByte(in);
}
@Override
public void write(final int value, final OutputStream out) throws IOException {
//To change body of implemented methods use File | Settings | File Templates.
}
},
INT16(2, 2, 0xFFFF8000, -32767, 32767) {
@Override
public int read(final InputStream in) throws IOException {
final int b2 = BCF2Utils.readByte(in) & 0xFF;
final int b1 = BCF2Utils.readByte(in) & 0xFF;
return (short)((b1 << 8) | b2);
}
@Override
public void write(final int value, final OutputStream out) throws IOException {
//To change body of implemented methods use File | Settings | File Templates.
}
},
INT32(3, 4, 0x80000000, -2147483647, 2147483647) {
@Override
public int read(final InputStream in) throws IOException {
final int b4 = BCF2Utils.readByte(in) & 0xFF;
final int b3 = BCF2Utils.readByte(in) & 0xFF;
final int b2 = BCF2Utils.readByte(in) & 0xFF;
final int b1 = BCF2Utils.readByte(in) & 0xFF;
return (int)(b1 << 24 | b2 << 16 | b3 << 8 | b4);
}
@Override
public void write(final int value, final OutputStream out) throws IOException {
//To change body of implemented methods use File | Settings | File Templates.
}
},
FLOAT(5, 4, 0x7F800001) {
@Override
public int read(final InputStream in) throws IOException {
return INT32.read(in);
}
@Override
public void write(final int value, final OutputStream out) throws IOException {
//To change body of implemented methods use File | Settings | File Templates.
}
},
CHAR (7, 1, 0x00000000) {
@Override
public int read(final InputStream in) throws IOException {
return INT8.read(in);
}
@Override
public void write(final int value, final OutputStream out) throws IOException {
//To change body of implemented methods use File | Settings | File Templates.
}
};
private final int id;
private final Object missingJavaValue;
@ -48,10 +121,6 @@ public enum BCF2Type {
private final int sizeInBytes;
private final long minValue, maxValue;
BCF2Type(final int id) {
this(id, -1, 0, 0, 0);
}
BCF2Type(final int id, final int sizeInBytes, final int missingBytes) {
this(id, sizeInBytes, missingBytes, 0, 0);
}
@ -121,4 +190,25 @@ public enum BCF2Type {
public boolean isIntegerType() {
return INTEGERS.contains(this);
}
/**
* Read a value from in stream of this BCF2 type as an int [32 bit] collection of bits
*
* For intX and char values this is just the int / byte value of the underlying data represented as a 32 bit int
* For a char the result must be converted to a char by (char)(byte)(0x0F & value)
* For doubles it's necessary to convert subsequently this value to a double via Double.bitsToDouble()
*
* @param in
* @return
* @throws IOException
*/
@Requires("in != null")
public int read(final InputStream in) throws IOException {
throw new IllegalArgumentException("Not implemented");
}
@Requires("out != null")
public void write(final int value, final OutputStream out) throws IOException {
throw new IllegalArgumentException("Not implemented");
}
}

View File

@ -282,26 +282,6 @@ public final class BCF2Utils {
else return Collections.singletonList(o);
}
@Requires({"stream != null", "bytesForEachInt > 0"})
public static int readInt(int bytesForEachInt, final InputStream stream) throws IOException {
switch ( bytesForEachInt ) {
case 1: {
return (byte)(readByte(stream));
} case 2: {
final int b2 = readByte(stream) & 0xFF;
final int b1 = readByte(stream) & 0xFF;
return (short)((b1 << 8) | b2);
} case 4: {
final int b4 = readByte(stream) & 0xFF;
final int b3 = readByte(stream) & 0xFF;
final int b2 = readByte(stream) & 0xFF;
final int b1 = readByte(stream) & 0xFF;
return (int)(b1 << 24 | b2 << 16 | b3 << 8 | b4);
} default: throw new ReviewedStingException("Unexpected size during decoding");
}
}
public static void encodeRawBytes(final int value, final BCF2Type type, final OutputStream encodeStream) throws IOException {
switch ( type.getSizeInBytes() ) {
case 1: