From 073d3aecdfee7c11bc40e189defb7e2cd5d498cb Mon Sep 17 00:00:00 2001 From: Artsiom Korzun <72259616+artsiomkorzun@users.noreply.github.com> Date: Mon, 15 Jan 2024 21:07:53 +0100 Subject: [PATCH] native version (#434) --- calculate_average_artsiomkorzun.sh | 10 ++++-- prepare_artsiomkorzun.sh | 5 +++ .../CalculateAverage_artsiomkorzun.java | 36 ++++++++++++------- 3 files changed, 36 insertions(+), 15 deletions(-) diff --git a/calculate_average_artsiomkorzun.sh b/calculate_average_artsiomkorzun.sh index 96e3467..d9c1828 100755 --- a/calculate_average_artsiomkorzun.sh +++ b/calculate_average_artsiomkorzun.sh @@ -15,5 +15,11 @@ # limitations under the License. # -JAVA_OPTS="--enable-preview -Xmx128m -XX:+UseSerialGC -XX:-TieredCompilation" -java $JAVA_OPTS --class-path target/average-1.0.0-SNAPSHOT.jar dev.morling.onebrc.CalculateAverage_artsiomkorzun +if [ -f target/CalculateAverage_artsiomkorzun_image ]; then + echo "Picking up existing native image 'target/CalculateAverage_artsiomkorzun_image', delete the file to select JVM mode." 1>&2 + target/CalculateAverage_artsiomkorzun_image +else + JAVA_OPTS="--enable-preview -Xmx128m -XX:+UseSerialGC -XX:-TieredCompilation" + echo "Chosing to run the app in JVM mode as no native image was found, use prepare_artsiomkorzun.sh to generate." 1>&2 + java $JAVA_OPTS --class-path target/average-1.0.0-SNAPSHOT.jar dev.morling.onebrc.CalculateAverage_artsiomkorzun +fi \ No newline at end of file diff --git a/prepare_artsiomkorzun.sh b/prepare_artsiomkorzun.sh index f83a3ff..9ae693a 100755 --- a/prepare_artsiomkorzun.sh +++ b/prepare_artsiomkorzun.sh @@ -17,3 +17,8 @@ source "$HOME/.sdkman/bin/sdkman-init.sh" sdk use java 21.0.1-graal 1>&2 + +if [ ! -f target/CalculateAverage_artsiomkorzun_image ]; then + NATIVE_IMAGE_OPTS="--gc=epsilon -O3 -march=native -R:MaxHeapSize=64m --enable-preview --initialize-at-build-time=dev.morling.onebrc.CalculateAverage_artsiomkorzun" + native-image $NATIVE_IMAGE_OPTS -cp target/average-1.0.0-SNAPSHOT.jar -o target/CalculateAverage_artsiomkorzun_image dev.morling.onebrc.CalculateAverage_artsiomkorzun +fi \ No newline at end of file diff --git a/src/main/java/dev/morling/onebrc/CalculateAverage_artsiomkorzun.java b/src/main/java/dev/morling/onebrc/CalculateAverage_artsiomkorzun.java index f92f414..4ea9d58 100644 --- a/src/main/java/dev/morling/onebrc/CalculateAverage_artsiomkorzun.java +++ b/src/main/java/dev/morling/onebrc/CalculateAverage_artsiomkorzun.java @@ -31,12 +31,8 @@ import java.util.concurrent.atomic.AtomicReference; public class CalculateAverage_artsiomkorzun { private static final Path FILE = Path.of("./measurements.txt"); - private static final MemorySegment MAPPED_FILE = map(FILE); - - private static final int PARALLELISM = Runtime.getRuntime().availableProcessors(); - private static final int SEGMENT_SIZE = 32 * 1024 * 1024; - private static final int SEGMENT_COUNT = (int) ((MAPPED_FILE.byteSize() + SEGMENT_SIZE - 1) / SEGMENT_SIZE); - private static final int SEGMENT_OVERLAP = 1024; + private static final long SEGMENT_SIZE = 32 * 1024 * 1024; + private static final long SEGMENT_OVERLAP = 1024; private static final long COMMA_PATTERN = 0x3B3B3B3B3B3B3B3BL; private static final long DOT_BITS = 0x10101000; private static final long MAGIC_MULTIPLIER = (100 * 0x1000000 + 10 * 0x10000 + 1); @@ -66,12 +62,19 @@ public class CalculateAverage_artsiomkorzun { } private static void execute() throws Exception { + MemorySegment fileMemory = map(FILE); + long fileAddress = fileMemory.address(); + long fileSize = fileMemory.byteSize(); + int segmentCount = (int) ((fileSize + SEGMENT_SIZE - 1) / SEGMENT_SIZE); + AtomicInteger counter = new AtomicInteger(); AtomicReference result = new AtomicReference<>(); - Aggregator[] aggregators = new Aggregator[PARALLELISM]; + + int parallelism = Runtime.getRuntime().availableProcessors(); + Aggregator[] aggregators = new Aggregator[parallelism]; for (int i = 0; i < aggregators.length; i++) { - aggregators[i] = new Aggregator(counter, result); + aggregators[i] = new Aggregator(counter, result, fileAddress, fileSize, segmentCount); aggregators[i].start(); } @@ -306,21 +309,28 @@ public class CalculateAverage_artsiomkorzun { private final AtomicInteger counter; private final AtomicReference result; + private final long fileAddress; + private final long fileSize; + private final int segmentCount; - public Aggregator(AtomicInteger counter, AtomicReference result) { + public Aggregator(AtomicInteger counter, AtomicReference result, + long fileAddress, long fileSize, int segmentCount) { super("aggregator"); this.counter = counter; this.result = result; + this.fileAddress = fileAddress; + this.fileSize = fileSize; + this.segmentCount = segmentCount; } @Override public void run() { Aggregates aggregates = new Aggregates(); - for (int segment; (segment = counter.getAndIncrement()) < SEGMENT_COUNT;) { - long position = (long) SEGMENT_SIZE * segment; - int size = (int) Math.min(SEGMENT_SIZE + SEGMENT_OVERLAP, MAPPED_FILE.byteSize() - position); - long address = MAPPED_FILE.address() + position; + for (int segment; (segment = counter.getAndIncrement()) < segmentCount;) { + long position = SEGMENT_SIZE * segment; + long size = Math.min(SEGMENT_SIZE + SEGMENT_OVERLAP, fileSize - position); + long address = fileAddress + position; long limit = address + Math.min(SEGMENT_SIZE, size - 1); if (segment > 0) {