aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/dev/morling/onebrc
diff options
context:
space:
mode:
authorJohn Ziamos <iziamos@gmail.com>2024-01-17 20:41:32 +0000
committerGitHub <noreply@github.com>2024-01-17 21:41:32 +0100
commit4d7d9fb34e1b580d562d769c885acfcc9c46bae5 (patch)
tree5025afa5effbc6704990eaef856747fe437e4aa7 /src/main/java/dev/morling/onebrc
parent199d6415bb66b5a3fb3e77958a056d1e4adcef5c (diff)
extract cursor interface (#458)
'pull' mery kitty number parsing code try out tonne of flags (found via trial and error on my system)
Diffstat (limited to 'src/main/java/dev/morling/onebrc')
-rw-r--r--src/main/java/dev/morling/onebrc/CalculateAverage_iziamos.java89
1 files changed, 43 insertions, 46 deletions
diff --git a/src/main/java/dev/morling/onebrc/CalculateAverage_iziamos.java b/src/main/java/dev/morling/onebrc/CalculateAverage_iziamos.java
index c0358b9..ad2bf05 100644
--- a/src/main/java/dev/morling/onebrc/CalculateAverage_iziamos.java
+++ b/src/main/java/dev/morling/onebrc/CalculateAverage_iziamos.java
@@ -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++);
-
- 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);
+ return getCurrentValueMeryKitty();
+ }
+
+ /**
+ * 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) {