From 8c5aaf2db90f3d66fc9c1764ff01959d5740d9e4 Mon Sep 17 00:00:00 2001 From: Filip Hrisafov Date: Wed, 3 Jan 2024 23:28:03 +0100 Subject: [PATCH] Manually compute temperature value instead of using Long.parseLong --- .../onebrc/CalculateAverage_filiphr.java | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/main/java/dev/morling/onebrc/CalculateAverage_filiphr.java b/src/main/java/dev/morling/onebrc/CalculateAverage_filiphr.java index 5e1b705..7eabba7 100644 --- a/src/main/java/dev/morling/onebrc/CalculateAverage_filiphr.java +++ b/src/main/java/dev/morling/onebrc/CalculateAverage_filiphr.java @@ -41,6 +41,7 @@ import java.util.stream.StreamSupport; * Using big decimal and iterating the buffer once: 0m 20s * Using long parse: 0m 11s * Using array hash code for city key: 0m 7.1s + * Manually compute the value: 0m 6.8s *

* Using 21.0.1 Temurin with ShenandoahGC on Macbook (Intel) Pro * `sdk use java 21.0.1-tem` @@ -156,10 +157,6 @@ public class CalculateAverage_filiphr { Map measurements = HashMap.newHashMap(415); int limit = bb.limit(); byte[] cityBuffer = new byte[128]; - char[] charArray = new char[8]; - CharBuffer charBuffer = CharBuffer.wrap(charArray); - charBuffer.clear(); - charBuffer.position(0); while (bb.position() < limit) { int cityBufferIndex = 0; @@ -177,20 +174,29 @@ public class CalculateAverage_filiphr { } byte lastPositionByte = '\n'; - int temperatureBufferIndex = 0; + boolean negative = false; + long value = 0; while (bb.position() < limit) { byte positionByte = bb.get(); if (positionByte == '\r' || positionByte == '\n') { lastPositionByte = positionByte; break; } + else if (positionByte == '-') { + negative = true; + } else if (positionByte != '.') { - charArray[temperatureBufferIndex++] = (char) positionByte; + // The 0 to 9 characters have an int value of 48 (for 0) to 57 (for 9) + // Therefore, in order to compute the digit we subtract with 48 + int digit = positionByte - 48; + // We are computing the value by hand (in order to avoid iterating the index twice) + value = value * 10 + digit; } } - // Create the temperature - long value = Long.parseLong(charBuffer, 0, temperatureBufferIndex, 10); + if (negative) { + value = -value; + } Measurement measurement = measurements.get(cityKey); if (measurement == null) {