BCF2 optimizations
-- Added Write method to BCF2 types that directly converts int value to byte stream. Deleted writeRawBytes(int) -- encodeTypeDescriptor semi-inlined into encodeType so that the tests for overflow are done in just one place -- Faster implementation of determineIntegerType for int[] values
This commit is contained in:
parent
c6bd9b15ff
commit
06258c8a01
|
|
@ -295,7 +295,7 @@ public final class BCF2Decoder {
|
||||||
return decodeIntArray(size, type, null);
|
return decodeIntArray(size, type, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final double rawFloatToFloat(final int rawFloat) {
|
private double rawFloatToFloat(final int rawFloat) {
|
||||||
return (double)Float.intBitsToFloat(rawFloat);
|
return (double)Float.intBitsToFloat(rawFloat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ public enum BCF2Type {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(final int value, final OutputStream out) throws IOException {
|
public void write(final int value, final OutputStream out) throws IOException {
|
||||||
//To change body of implemented methods use File | Settings | File Templates.
|
out.write(0xFF & value); // TODO -- do we need this operation?
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -71,7 +71,9 @@ public enum BCF2Type {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(final int value, final OutputStream out) throws IOException {
|
public void write(final int value, final OutputStream out) throws IOException {
|
||||||
//To change body of implemented methods use File | Settings | File Templates.
|
// TODO -- optimization -- should we put this in a local buffer?
|
||||||
|
out.write((0x00FF & value));
|
||||||
|
out.write((0xFF00 & value) >> 8);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -87,7 +89,10 @@ public enum BCF2Type {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(final int value, final OutputStream out) throws IOException {
|
public void write(final int value, final OutputStream out) throws IOException {
|
||||||
//To change body of implemented methods use File | Settings | File Templates.
|
out.write((0x000000FF & value));
|
||||||
|
out.write((0x0000FF00 & value) >> 8);
|
||||||
|
out.write((0x00FF0000 & value) >> 16);
|
||||||
|
out.write((0xFF000000 & value) >> 24);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -99,7 +104,7 @@ public enum BCF2Type {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(final int value, final OutputStream out) throws IOException {
|
public void write(final int value, final OutputStream out) throws IOException {
|
||||||
//To change body of implemented methods use File | Settings | File Templates.
|
INT32.write(value, out);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -111,7 +116,7 @@ public enum BCF2Type {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(final int value, final OutputStream out) throws IOException {
|
public void write(final int value, final OutputStream out) throws IOException {
|
||||||
//To change body of implemented methods use File | Settings | File Templates.
|
INT8.write(value, out);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -95,10 +95,9 @@ public final class BCF2Utils {
|
||||||
return dict;
|
return dict;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Requires({"nElements >= 0", "type != null"})
|
@Requires({"nElements >= 0", "nElements <= OVERFLOW_ELEMENT_MARKER", "type != null"})
|
||||||
public static byte encodeTypeDescriptor(final int nElements, final BCF2Type type ) {
|
public static byte encodeTypeDescriptor(final int nElements, final BCF2Type type ) {
|
||||||
final int encodeSize = nElements > MAX_INLINE_ELEMENTS ? OVERFLOW_ELEMENT_MARKER : nElements;
|
return (byte)((0x0F & nElements) << 4 | (type.getID() & 0x0F));
|
||||||
return (byte)((0x0F & encodeSize) << 4 | (type.getID() & 0x0F));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Ensures("result >= 0")
|
@Ensures("result >= 0")
|
||||||
|
|
@ -216,18 +215,18 @@ public final class BCF2Utils {
|
||||||
|
|
||||||
@Ensures("result.isIntegerType()")
|
@Ensures("result.isIntegerType()")
|
||||||
public static BCF2Type determineIntegerType(final int[] values) {
|
public static BCF2Type determineIntegerType(final int[] values) {
|
||||||
// literally a copy of the code below, but there's no general way to unify lists and arrays in java
|
// find the min and max values in the array
|
||||||
BCF2Type maxType = BCF2Type.INT8;
|
int max = 0, min = 0;
|
||||||
for ( final int value : values ) {
|
for ( final int v : values ) {
|
||||||
final BCF2Type type1 = determineIntegerType(value);
|
if ( v > max ) max = v;
|
||||||
switch ( type1 ) {
|
if ( v < min ) min = v;
|
||||||
case INT8: break;
|
|
||||||
case INT16: maxType = BCF2Type.INT16; break;
|
|
||||||
case INT32: return BCF2Type.INT32; // fast path for largest possible value
|
|
||||||
default: throw new ReviewedStingException("Unexpected integer type " + type1 );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return maxType;
|
|
||||||
|
final BCF2Type maxType = determineIntegerType(max);
|
||||||
|
final BCF2Type minType = determineIntegerType(min);
|
||||||
|
|
||||||
|
// INT8 < INT16 < INT32 so this returns the larger of the two
|
||||||
|
return maxType.compareTo(minType) >= 0 ? maxType : minType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -281,31 +280,4 @@ public final class BCF2Utils {
|
||||||
else if ( o instanceof List ) return (List<Object>)o;
|
else if ( o instanceof List ) return (List<Object>)o;
|
||||||
else return Collections.singletonList(o);
|
else return Collections.singletonList(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void encodeRawBytes(final int value, final BCF2Type type, final OutputStream encodeStream) throws IOException {
|
|
||||||
switch ( type.getSizeInBytes() ) {
|
|
||||||
case 1:
|
|
||||||
encodeStream.write(0xFF & value);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
encodeStream.write((0x00FF & value));
|
|
||||||
encodeStream.write((0xFF00 & value) >> 8);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
encodeStream.write((0x000000FF & value));
|
|
||||||
encodeStream.write((0x0000FF00 & value) >> 8);
|
|
||||||
encodeStream.write((0x00FF0000 & value) >> 16);
|
|
||||||
encodeStream.write((0xFF000000 & value) >> 24);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new ReviewedStingException("BUG: unexpected type size " + type);
|
|
||||||
}
|
|
||||||
// general case for reference
|
|
||||||
// for ( int i = type.getSizeInBytes() - 1; i >= 0; i-- ) {
|
|
||||||
// final int shift = i * 8;
|
|
||||||
// int mask = 0xFF << shift;
|
|
||||||
// int byteValue = (mask & value) >> shift;
|
|
||||||
// encodeStream.write(byteValue);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -191,9 +191,12 @@ public final class BCF2Encoder {
|
||||||
@Requires("size >= 0")
|
@Requires("size >= 0")
|
||||||
@Ensures("encodeStream.size() > old(encodeStream.size())")
|
@Ensures("encodeStream.size() > old(encodeStream.size())")
|
||||||
public final void encodeType(final int size, final BCF2Type type) throws IOException {
|
public final void encodeType(final int size, final BCF2Type type) throws IOException {
|
||||||
final byte typeByte = BCF2Utils.encodeTypeDescriptor(size, type);
|
if ( size <= BCF2Utils.MAX_INLINE_ELEMENTS ) {
|
||||||
encodeStream.write(typeByte);
|
final int typeByte = BCF2Utils.encodeTypeDescriptor(size, type);
|
||||||
if ( size > BCF2Utils.MAX_INLINE_ELEMENTS ) {
|
encodeStream.write(typeByte);
|
||||||
|
} else {
|
||||||
|
final int typeByte = BCF2Utils.encodeTypeDescriptor(BCF2Utils.OVERFLOW_ELEMENT_MARKER, type);
|
||||||
|
encodeStream.write(typeByte);
|
||||||
// write in the overflow size
|
// write in the overflow size
|
||||||
encodeTypedInt(size);
|
encodeTypedInt(size);
|
||||||
}
|
}
|
||||||
|
|
@ -201,12 +204,12 @@ public final class BCF2Encoder {
|
||||||
|
|
||||||
@Ensures("encodeStream.size() > old(encodeStream.size())")
|
@Ensures("encodeStream.size() > old(encodeStream.size())")
|
||||||
public final void encodeRawInt(final int value, final BCF2Type type) throws IOException {
|
public final void encodeRawInt(final int value, final BCF2Type type) throws IOException {
|
||||||
BCF2Utils.encodeRawBytes(value, type, encodeStream);
|
type.write(value, encodeStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Ensures("encodeStream.size() > old(encodeStream.size())")
|
@Ensures("encodeStream.size() > old(encodeStream.size())")
|
||||||
public final void encodeRawBytes(final int value, final BCF2Type type) throws IOException {
|
public final void encodeRawBytes(final int value, final BCF2Type type) throws IOException {
|
||||||
BCF2Utils.encodeRawBytes(value, type, encodeStream);
|
type.write(value, encodeStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -158,7 +158,7 @@ class BCF2Writer extends IndexingVariantContextWriter {
|
||||||
|
|
||||||
final byte[] headerBytes = capture.toByteArray();
|
final byte[] headerBytes = capture.toByteArray();
|
||||||
new BCFVersion(MAJOR_VERSION, MINOR_VERSION).write(outputStream);
|
new BCFVersion(MAJOR_VERSION, MINOR_VERSION).write(outputStream);
|
||||||
BCF2Utils.encodeRawBytes(headerBytes.length, BCF2Type.INT32, outputStream);
|
BCF2Type.INT32.write(headerBytes.length, outputStream);
|
||||||
outputStream.write(headerBytes);
|
outputStream.write(headerBytes);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new UserException.CouldNotCreateOutputFile("BCF2 stream", "Got IOException while trying to write BCF2 header", e);
|
throw new UserException.CouldNotCreateOutputFile("BCF2 stream", "Got IOException while trying to write BCF2 header", e);
|
||||||
|
|
@ -359,8 +359,8 @@ class BCF2Writer extends IndexingVariantContextWriter {
|
||||||
*/
|
*/
|
||||||
@Requires({"infoBlock.length > 0", "genotypesBlock.length >= 0"})
|
@Requires({"infoBlock.length > 0", "genotypesBlock.length >= 0"})
|
||||||
private void writeBlock(final byte[] infoBlock, final byte[] genotypesBlock) throws IOException {
|
private void writeBlock(final byte[] infoBlock, final byte[] genotypesBlock) throws IOException {
|
||||||
BCF2Utils.encodeRawBytes(infoBlock.length, BCF2Type.INT32, outputStream);
|
BCF2Type.INT32.write(infoBlock.length, outputStream);
|
||||||
BCF2Utils.encodeRawBytes(genotypesBlock.length, BCF2Type.INT32, outputStream);
|
BCF2Type.INT32.write(genotypesBlock.length, outputStream);
|
||||||
outputStream.write(infoBlock);
|
outputStream.write(infoBlock);
|
||||||
outputStream.write(genotypesBlock);
|
outputStream.write(genotypesBlock);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue