dashboard #1
@@ -28,15 +28,10 @@ public class VariableByteEncoder {
|
|||||||
public static final long MIN_VALUE = Long.MIN_VALUE / 2 + 1;
|
public static final long MIN_VALUE = Long.MIN_VALUE / 2 + 1;
|
||||||
public static final long MAX_VALUE = Long.MAX_VALUE / 2;
|
public static final long MAX_VALUE = Long.MAX_VALUE / 2;
|
||||||
|
|
||||||
private static final int MAX_BYTES_PER_VALUE = 10;
|
|
||||||
|
|
||||||
private static final int CONTINUATION_BYTE_FLAG = 1 << 7; // 10000000
|
private static final int CONTINUATION_BYTE_FLAG = 1 << 7; // 10000000
|
||||||
|
|
||||||
private static final long DATA_BITS = (1 << 7) - 1; // 01111111
|
private static final long DATA_BITS = (1 << 7) - 1; // 01111111
|
||||||
|
|
||||||
private static final ThreadLocal<byte[]> SINGLE_VALUE_BUFFER = ThreadLocal
|
|
||||||
.withInitial(() -> new byte[MAX_BYTES_PER_VALUE]);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encodes time and value into the given buffer.
|
* Encodes time and value into the given buffer.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -137,8 +132,18 @@ public class VariableByteEncoder {
|
|||||||
* input: 0 1 -1 2 -2 3 -3
|
* input: 0 1 -1 2 -2 3 -3
|
||||||
* encoded: 1 2 3 4 5 6 7
|
* encoded: 1 2 3 4 5 6 7
|
||||||
* </pre>
|
* </pre>
|
||||||
|
*
|
||||||
|
* Note: 1. I tried to replace this ternary operator with a branchfree
|
||||||
|
* alternative, but it was slower:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* final long sign = (x - 1) >> 63; // will be 111...1 if first bit was 1 (x was negative) and 000..0
|
||||||
|
* // otherwise
|
||||||
|
* final long signBit = sign & 0x1; // will be 1 for negative x and 0 otherwise
|
||||||
|
* return (((x * 2) ^ (sign))) + (signBit * 2); // same as above, but branchless
|
||||||
|
* </pre>
|
||||||
*/
|
*/
|
||||||
private static long encodeIntoPositiveValue(final long value) {
|
static long encodeIntoPositiveValue(final long value) {
|
||||||
return value > 0 ? value * 2 : (value * -2) + 1;
|
return value > 0 ? value * 2 : (value * -2) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,9 +239,9 @@ public class VariableByteEncoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static int neededBytes(final long value) {
|
public static int neededBytes(final long value) {
|
||||||
final byte[] buffer = SINGLE_VALUE_BUFFER.get();
|
final long val = encodeIntoPositiveValue(value);
|
||||||
final int usedBytes = encodeInto(value, buffer, 0);
|
final int numberOfOnes = 64 - Long.numberOfLeadingZeros(val);
|
||||||
return usedBytes;
|
return numberOfOnes / 7 + (numberOfOnes % 7 == 0 ? 0 : 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ public class VariableByteEncoderTest {
|
|||||||
Assertions.assertEquals(originalValues, decodedValues);
|
Assertions.assertEquals(originalValues, decodedValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Stream<Arguments> providerNededBytes() {
|
public static Stream<Arguments> providerNeededBytes() {
|
||||||
return Stream.of( //
|
return Stream.of( //
|
||||||
Arguments.of(0, 1), //
|
Arguments.of(0, 1), //
|
||||||
Arguments.of(-10, 1), //
|
Arguments.of(-10, 1), //
|
||||||
@@ -98,7 +98,7 @@ public class VariableByteEncoderTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("providerNededBytes")
|
@MethodSource("providerNeededBytes")
|
||||||
public void testNeededBytes(final long value, final int expectedNeededBytes) {
|
public void testNeededBytes(final long value, final int expectedNeededBytes) {
|
||||||
|
|
||||||
final int neededBytes = VariableByteEncoder.neededBytes(value);
|
final int neededBytes = VariableByteEncoder.neededBytes(value);
|
||||||
|
|||||||
Reference in New Issue
Block a user