diff options
| author | Roman Romanchuk <fatroom@users.noreply.github.com> | 2024-01-12 09:52:32 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-01-12 09:52:32 +0100 |
| commit | 594f6c4e5fc2df488070de141ac874a0d78d7c20 (patch) | |
| tree | 0a2b7234c4d5e2015ede2f244f5004ccecdb130c /src/main | |
| parent | 10f425e2b65675210b86685496078cfd184ec359 (diff) | |
Lazy strings init, custom station map (#336)
Diffstat (limited to 'src/main')
| -rw-r--r-- | src/main/java/dev/morling/onebrc/CalculateAverage_fatroom.java | 56 |
1 files changed, 36 insertions, 20 deletions
diff --git a/src/main/java/dev/morling/onebrc/CalculateAverage_fatroom.java b/src/main/java/dev/morling/onebrc/CalculateAverage_fatroom.java index 7fa9b2e..340096f 100644 --- a/src/main/java/dev/morling/onebrc/CalculateAverage_fatroom.java +++ b/src/main/java/dev/morling/onebrc/CalculateAverage_fatroom.java @@ -69,7 +69,7 @@ public class CalculateAverage_fatroom { long fileSize = file.length(); long position = 0; - List<Callable<Map<Station, MeasurementAggregator>>> tasks = new LinkedList<>(); + List<Callable<StationMap>> tasks = new LinkedList<>(); while (position < fileSize) { long end = Math.min(position + SEGMENT_LENGTH, fileSize); int length = (int) (end - position); @@ -88,7 +88,7 @@ public class CalculateAverage_fatroom { for (var future : executor.invokeAll(tasks)) { var segmentAggregates = future.get(); for (var entry : segmentAggregates.entrySet()) { - aggregates.merge(entry.getKey().toString(), entry.getValue(), MeasurementAggregator::combineWith); + aggregates.merge(entry.getKey(), entry.value, MeasurementAggregator::combineWith); } } executor.shutdown(); @@ -99,10 +99,8 @@ public class CalculateAverage_fatroom { System.out.println(aggregates); } - private static Map<Station, MeasurementAggregator> processBuffer(MappedByteBuffer source, int length) { - - Map<Station, MeasurementAggregator> aggregates = new HashMap<>(500); - Station station; + private static StationMap processBuffer(MappedByteBuffer source, int length) { + StationMap aggregates = new StationMap(); byte[] buffer = new byte[200]; byte[] measurement = new byte[5]; int measurementLength; @@ -113,7 +111,6 @@ public class CalculateAverage_fatroom { hash = 31 * hash + b; buffer[idx++] = b; if (b == ';') { - station = new Station(hash, buffer, idx - 1); measurementLength = 3; measurement[0] = source.get(++i); measurement[1] = source.get(++i); @@ -127,7 +124,7 @@ public class CalculateAverage_fatroom { measurementLength++; } } - aggregates.computeIfAbsent(station, s -> new MeasurementAggregator()).consume(parseMeasurement(measurement, measurementLength)); + aggregates.get(hash, buffer, idx - 1).consume(parseMeasurement(measurement, measurementLength)); idx = 0; hash = 1; } @@ -148,28 +145,47 @@ public class CalculateAverage_fatroom { static class Station { private byte[] bytes; private int hash; + private MeasurementAggregator value; + private Station next; - public Station(int hash, byte[] bytes, int length) { + public Station(int hash, byte[] bytes, int length, Station next) { + this.hash = hash; this.bytes = new byte[length]; System.arraycopy(bytes, 0, this.bytes, 0, length); - this.hash = hash; + this.value = new MeasurementAggregator(); + this.next = next; } - public String toString() { + public String getKey() { return new String(bytes, 0, bytes.length, StandardCharsets.UTF_8); } + } - @Override - public boolean equals(Object o) { - Station station = (Station) o; - if (hash != station.hash) - return false; - return Arrays.equals(bytes, station.bytes); + static class StationMap { + private Station[] stations = new Station[16384]; + + MeasurementAggregator get(int hash, byte[] buffer, int length) { + int bucketId = hash & 0x3fff; + Station entry = stations[bucketId]; + while (entry != null) { + if (entry.hash == hash && Arrays.equals(entry.bytes, 0, entry.bytes.length, buffer, 0, length)) { + return entry.value; + } + entry = entry.next; + } + stations[bucketId] = new Station(hash, buffer, length, stations[bucketId]); + return stations[bucketId].value; } - @Override - public int hashCode() { - return hash; + private List<Station> entrySet() { + List<Station> result = new LinkedList<>(); + for (var station : stations) { + while (station != null) { + result.add(station); + station = station.next; + } + } + return result; } } } |
