Use long parse and use char array instead of CharBuffer for adding to it

This commit is contained in:
Filip Hrisafov 2024-01-03 22:06:33 +01:00 committed by Gunnar Morling
parent 88b1c30db8
commit 4a483b4097

View File

@ -17,7 +17,6 @@ package dev.morling.onebrc;
import java.io.IOException; import java.io.IOException;
import java.io.UncheckedIOException; import java.io.UncheckedIOException;
import java.math.BigDecimal;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.CharBuffer; import java.nio.CharBuffer;
import java.nio.MappedByteBuffer; import java.nio.MappedByteBuffer;
@ -40,6 +39,7 @@ import java.util.stream.StreamSupport;
* Initial submission: 1m 35s * Initial submission: 1m 35s
* Adding memory mapped files: 0m 55s (based on bjhara's submission) * Adding memory mapped files: 0m 55s (based on bjhara's submission)
* Using big decimal and iterating the buffer once: 0m 20s * Using big decimal and iterating the buffer once: 0m 20s
* Using long parse: 0m 11s
* <p> * <p>
* Using 21.0.1 Temurin with ShenandoahGC on Macbook (Intel) Pro * Using 21.0.1 Temurin with ShenandoahGC on Macbook (Intel) Pro
* `sdk use java 21.0.1-tem` * `sdk use java 21.0.1-tem`
@ -59,12 +59,12 @@ public class CalculateAverage_filiphr {
private static final class Measurement { private static final class Measurement {
private double min = Long.MAX_VALUE; private long min = Long.MAX_VALUE;
private double max = Long.MIN_VALUE; private long max = Long.MIN_VALUE;
private double sum = 0L; private long sum = 0L;
private long count = 0L; private long count = 0L;
private void add(double value) { private void add(long value) {
this.min = Math.min(this.min, value); this.min = Math.min(this.min, value);
this.max = Math.max(this.max, value); this.max = Math.max(this.max, value);
this.sum += value; this.sum += value;
@ -82,7 +82,7 @@ public class CalculateAverage_filiphr {
@Override @Override
public String toString() { public String toString() {
return round(min) + "/" + round((sum) / count) + "/" + round(max); return round(min / 10.0) + "/" + round((sum / 10.0) / count) + "/" + round(max / 10.0);
} }
private double round(double value) { private double round(double value) {
@ -143,7 +143,10 @@ public class CalculateAverage_filiphr {
Map<String, Measurement> measurements = HashMap.newHashMap(415); Map<String, Measurement> measurements = HashMap.newHashMap(415);
int limit = bb.limit(); int limit = bb.limit();
byte[] buffer = new byte[128]; byte[] buffer = new byte[128];
CharBuffer charBuffer = CharBuffer.allocate(8); char[] charArray = new char[8];
CharBuffer charBuffer = CharBuffer.wrap(charArray);
charBuffer.clear();
charBuffer.position(0);
while (bb.position() < limit) { while (bb.position() < limit) {
int bufferIndex = 0; int bufferIndex = 0;
@ -160,22 +163,21 @@ public class CalculateAverage_filiphr {
// Create the city // Create the city
String city = new String(buffer, 0, bufferIndex); String city = new String(buffer, 0, bufferIndex);
charBuffer.clear();
byte lastPositionByte = '\n'; byte lastPositionByte = '\n';
bufferIndex = 0;
while (bb.position() < limit) { while (bb.position() < limit) {
byte positionByte = bb.get(); byte positionByte = bb.get();
if (positionByte == '\r' || positionByte == '\n') { if (positionByte == '\r' || positionByte == '\n') {
lastPositionByte = positionByte; lastPositionByte = positionByte;
break; break;
} }
charBuffer.append((char) positionByte); else if (positionByte != '.') {
charArray[bufferIndex++] = (char) positionByte;
}
} }
int position = charBuffer.position();
charBuffer.position(0);
// Create the temperature string // Create the temperature string
BigDecimal bigDecimal = new BigDecimal(charBuffer.array(), 0, position); long value = Long.parseLong(charBuffer, 0, bufferIndex, 10);
double value = bigDecimal.doubleValue();
measurements.computeIfAbsent(city, k -> new Measurement()) measurements.computeIfAbsent(city, k -> new Measurement())
.add(value); .add(value);