extract cursor interface (#458)
'pull' mery kitty number parsing code try out tonne of flags (found via trial and error on my system)
This commit is contained in:
parent
199d6415bb
commit
4d7d9fb34e
@ -15,5 +15,11 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
JAVA_OPTS="--enable-preview --add-modules=jdk.incubator.vector -Djdk.incubator.vector.VECTOR_ACCESS_OOB_CHECK=0 -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -Xms16m -Xmx16m -XX:-AlwaysPreTouch -XX:-TieredCompilation -XX:CICompilerCount=1"
|
||||
JAVA_OPTS="--enable-preview
|
||||
-XX:+UnlockExperimentalVMOptions \
|
||||
-XX:+UseEpsilonGC -Xms16m -Xmx16m -XX:-AlwaysPreTouch \
|
||||
-XX:-TieredCompilation -XX:CICompilerCount=1 -XX:CompilationMode=high-only \
|
||||
-XX:C1MaxTrivialSize=500 -XX:-UseCountedLoopSafepoints -XX:+UseCMoveUnconditionally -XX:+DisableAttachMechanism \
|
||||
-XX:-PreserveFramePointer -Xnoclassgc -disablesystemassertions -XX:-UsePerfData \
|
||||
-XX:-UseTransparentHugePages -XX:-UseCompressedOops"
|
||||
java $JAVA_OPTS --class-path target/average-1.0.0-SNAPSHOT.jar dev.morling.onebrc.CalculateAverage_iziamos
|
||||
|
@ -21,6 +21,7 @@ import java.io.IOException;
|
||||
import java.lang.foreign.Arena;
|
||||
import java.lang.foreign.MemorySegment;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
@ -28,7 +29,6 @@ import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static dev.morling.onebrc.CalculateAverage_iziamos.ByteBackedResultSet.mask;
|
||||
import static java.nio.channels.FileChannel.MapMode.READ_ONLY;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static java.nio.file.StandardOpenOption.READ;
|
||||
@ -61,6 +61,7 @@ public class CalculateAverage_iziamos {
|
||||
BASE_POINTER = WHOLE_FILE_SEGMENT.address();
|
||||
END_POINTER = BASE_POINTER + FILE_SIZE;
|
||||
}
|
||||
|
||||
private static final long CHUNK_SIZE = 64 * 1024 * 1024;
|
||||
// private static final long CHUNK_SIZE = Long.MAX_VALUE;
|
||||
|
||||
@ -141,7 +142,7 @@ public class CalculateAverage_iziamos {
|
||||
}
|
||||
|
||||
private static void scalarLoop(final long start, final long limit, final long result) {
|
||||
final var cursor = new ScalarLoopCursor(start, limit);
|
||||
final LoopCursor cursor = new ScalarLoopCursor(start, limit);
|
||||
while (cursor.hasMore()) {
|
||||
final long address = cursor.getCurrentAddress();
|
||||
final int length = cursor.getStringLength();
|
||||
@ -151,7 +152,19 @@ public class CalculateAverage_iziamos {
|
||||
}
|
||||
}
|
||||
|
||||
public static class ScalarLoopCursor {
|
||||
public interface LoopCursor {
|
||||
long getCurrentAddress();
|
||||
|
||||
int getStringLength();
|
||||
|
||||
int getHash();
|
||||
|
||||
int getCurrentValue();
|
||||
|
||||
boolean hasMore();
|
||||
}
|
||||
|
||||
public static class ScalarLoopCursor implements LoopCursor {
|
||||
private long pointer;
|
||||
private final long limit;
|
||||
|
||||
@ -180,41 +193,35 @@ public class CalculateAverage_iziamos {
|
||||
}
|
||||
|
||||
public int getHash() {
|
||||
return mask(hash);
|
||||
return hash;
|
||||
}
|
||||
|
||||
public int getCurrentValue() {
|
||||
final byte first = UNSAFE.getByte(pointer++);
|
||||
final byte second = UNSAFE.getByte(pointer++);
|
||||
final byte third = UNSAFE.getByte(pointer++);
|
||||
final byte fourth = UNSAFE.getByte(pointer++);
|
||||
final byte fifth = UNSAFE.getByte(pointer++);
|
||||
return getCurrentValueMeryKitty();
|
||||
}
|
||||
|
||||
int value;
|
||||
if (second == '.') {
|
||||
// D.D\n
|
||||
value = appendDigit(digitCharToInt(first), third);
|
||||
pointer--;
|
||||
return value;
|
||||
}
|
||||
else if (fourth == '.') {
|
||||
// -DD.D\n
|
||||
value = digitCharToInt(second);
|
||||
value = appendDigit(value, third);
|
||||
value = -appendDigit(value, fifth);
|
||||
pointer++;
|
||||
return value;
|
||||
}
|
||||
else if (first == '-') {
|
||||
// -D.D\n
|
||||
return -appendDigit(digitCharToInt(second), fourth);
|
||||
}
|
||||
else {
|
||||
// DD.D\n
|
||||
value = digitCharToInt(first);
|
||||
value = appendDigit(value, second);
|
||||
return appendDigit(value, fourth);
|
||||
/**
|
||||
* No point rewriting what would essentially be the same code <3.
|
||||
*/
|
||||
public int getCurrentValueMeryKitty() {
|
||||
long word = UNSAFE.getLong(pointer);
|
||||
if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) {
|
||||
word = Long.reverseBytes(word);
|
||||
}
|
||||
|
||||
int decimalSepPos = Long.numberOfTrailingZeros(~word & 0x10101000);
|
||||
int shift = 28 - decimalSepPos;
|
||||
|
||||
long signed = (~word << 59) >> 63;
|
||||
long designMask = ~(signed & 0xFF);
|
||||
|
||||
long digits = ((word & designMask) << shift) & 0x0F000F0F00L;
|
||||
|
||||
long absValue = ((digits * 0x640a0001) >>> 32) & 0x3FF;
|
||||
int increment = (decimalSepPos >>> 3) + 3;
|
||||
|
||||
pointer += increment;
|
||||
return (int) ((absValue ^ signed) - signed);
|
||||
}
|
||||
|
||||
public boolean hasMore() {
|
||||
@ -222,22 +229,12 @@ public class CalculateAverage_iziamos {
|
||||
}
|
||||
}
|
||||
|
||||
private static int appendDigit(int value, final byte b) {
|
||||
value *= 10;
|
||||
value += digitCharToInt(b);
|
||||
return value;
|
||||
}
|
||||
|
||||
private static int digitCharToInt(final byte b) {
|
||||
return b - '0';
|
||||
}
|
||||
|
||||
public interface ResultConsumer {
|
||||
void consume(final String name, final int min, final int max, final long sum, final long count);
|
||||
}
|
||||
|
||||
static class ByteBackedResultSet {
|
||||
private static final int MAP_SIZE = 16384;
|
||||
private static final int MAP_SIZE = 16384 * 4;
|
||||
private static final int MASK = MAP_SIZE - 1;
|
||||
private static final long STRUCT_SIZE = 64;
|
||||
private static final long BYTE_SIZE = MAP_SIZE * STRUCT_SIZE;
|
||||
@ -338,7 +335,7 @@ public class CalculateAverage_iziamos {
|
||||
final long otherStringAddress,
|
||||
final int otherStringLength) {
|
||||
|
||||
for (int slot = hash;; slot = mask(++slot)) {
|
||||
for (int slot = mask(hash);; slot = mask(++slot)) {
|
||||
final long structBase = baseAddress + ((long) slot * STRUCT_SIZE);
|
||||
final long nameStart = UNSAFE.getLong(structBase);
|
||||
if (nameStart == 0) {
|
||||
|
Loading…
Reference in New Issue
Block a user