From 39452f53a376d9f13eefb0375e3d48c343b9acfa Mon Sep 17 00:00:00 2001 From: twobiers <22715034+twobiers@users.noreply.github.com> Date: Fri, 29 Dec 2023 23:56:06 +0100 Subject: [PATCH 01/18] First performance tweaks --- calculate_average_twobiers.sh | 20 ++++++ .../onebrc/CalculateAverage_twobiers.java | 61 +++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100755 calculate_average_twobiers.sh create mode 100644 src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java diff --git a/calculate_average_twobiers.sh b/calculate_average_twobiers.sh new file mode 100755 index 000000000..b2ff0fbcf --- /dev/null +++ b/calculate_average_twobiers.sh @@ -0,0 +1,20 @@ +#!/bin/sh +# +# Copyright 2023 The original authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + + +JAVA_OPTS="-XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -Xmx12g -XX:+UseStringDeduplication -XX:+UseLargePages" +java $JAVA_OPTS --class-path target/average-1.0.0-SNAPSHOT.jar dev.morling.onebrc.CalculateAverage_twobiers diff --git a/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java b/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java new file mode 100644 index 000000000..23aec9a81 --- /dev/null +++ b/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java @@ -0,0 +1,61 @@ +/* + * Copyright 2023 The original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dev.morling.onebrc; + +import static java.util.stream.Collectors.averagingDouble; +import static java.util.stream.Collectors.groupingBy; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Map; +import java.util.Map.Entry; +import java.util.TreeMap; +import java.util.stream.Collectors; + +public class CalculateAverage_twobiers { + + private static final String FILE = "./measurements.txt"; + + public static void main(String[] args) throws IOException { + Map measurements = Files.lines(Paths.get(FILE)) + .parallel() + .map(l -> fastSplit(l, ';')) + .collect(groupingBy(m -> m[0], averagingDouble(m -> Double.parseDouble(m[1])))); + + measurements = new TreeMap<>(measurements.entrySet().stream().collect(Collectors.toMap(Entry::getKey, e -> Math.round(e.getValue() * 10.0) / 10.0))); + + System.out.println(measurements); + } + + private static String[] fastSplit(String str, char delim) { + var splitArray = new String[2]; + var chars = str.toCharArray(); + + int i = 0; + for (char c : chars) { + if (c == delim) { + splitArray[0] = new String(Arrays.copyOfRange(chars, 0, i)); + break; + } + i++; + } + + splitArray[1] = new String(Arrays.copyOfRange(chars, i + 1, chars.length)); + return splitArray; + } +} From eed49f32586a136e850bb44ba48153ca01160747 Mon Sep 17 00:00:00 2001 From: twobiers <22715034+twobiers@users.noreply.github.com> Date: Sat, 30 Dec 2023 00:08:57 +0100 Subject: [PATCH 02/18] further tweaks --- calculate_average_twobiers.sh | 4 +- .../onebrc/CalculateAverage_twobiers.java | 86 ++++++++++++++++++- 2 files changed, 84 insertions(+), 6 deletions(-) diff --git a/calculate_average_twobiers.sh b/calculate_average_twobiers.sh index b2ff0fbcf..e8a688f65 100755 --- a/calculate_average_twobiers.sh +++ b/calculate_average_twobiers.sh @@ -15,6 +15,6 @@ # limitations under the License. # - -JAVA_OPTS="-XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -Xmx12g -XX:+UseStringDeduplication -XX:+UseLargePages" +# TODO: Adjust heap size and GC +JAVA_OPTS="-XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication -XX:+UseLargePages" java $JAVA_OPTS --class-path target/average-1.0.0-SNAPSHOT.jar dev.morling.onebrc.CalculateAverage_twobiers diff --git a/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java b/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java index 23aec9a81..bab57109d 100644 --- a/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java +++ b/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java @@ -34,21 +34,21 @@ public class CalculateAverage_twobiers { public static void main(String[] args) throws IOException { Map measurements = Files.lines(Paths.get(FILE)) .parallel() - .map(l -> fastSplit(l, ';')) - .collect(groupingBy(m -> m[0], averagingDouble(m -> Double.parseDouble(m[1])))); + .map(l -> fastSplit(l)) + .collect(groupingBy(m -> m[0], averagingDouble(m -> fastParseDouble(m[1])))); measurements = new TreeMap<>(measurements.entrySet().stream().collect(Collectors.toMap(Entry::getKey, e -> Math.round(e.getValue() * 10.0) / 10.0))); System.out.println(measurements); } - private static String[] fastSplit(String str, char delim) { + private static String[] fastSplit(String str) { var splitArray = new String[2]; var chars = str.toCharArray(); int i = 0; for (char c : chars) { - if (c == delim) { + if (c == ';') { splitArray[0] = new String(Arrays.copyOfRange(chars, 0, i)); break; } @@ -58,4 +58,82 @@ private static String[] fastSplit(String str, char delim) { splitArray[1] = new String(Arrays.copyOfRange(chars, i + 1, chars.length)); return splitArray; } + + private static Double fastParseDouble(String str) { + long value = 0; + int exp = 0; + boolean negative = false; + int decimalPlaces = Integer.MIN_VALUE; + var chars = str.toCharArray(); + for (char c : chars) { + if (c >= '0' && c <= '9') { + value = value * 10 + (c - '0'); + decimalPlaces++; + } + else if (c == '-') { + negative = true; + } + else if (c == '.') { + decimalPlaces = 0; + } + } + + return asDouble(value, exp, negative, decimalPlaces); + } + + private static double asDouble(long value, int exp, boolean negative, int decimalPlaces) { + if (decimalPlaces > 0 && value < Long.MAX_VALUE / 2) { + if (value < Long.MAX_VALUE / (1L << 32)) { + exp -= 32; + value <<= 32; + } + if (value < Long.MAX_VALUE / (1L << 16)) { + exp -= 16; + value <<= 16; + } + if (value < Long.MAX_VALUE / (1L << 8)) { + exp -= 8; + value <<= 8; + } + if (value < Long.MAX_VALUE / (1L << 4)) { + exp -= 4; + value <<= 4; + } + if (value < Long.MAX_VALUE / (1L << 2)) { + exp -= 2; + value <<= 2; + } + if (value < Long.MAX_VALUE / (1L << 1)) { + exp -= 1; + value <<= 1; + } + } + for (; decimalPlaces > 0; decimalPlaces--) { + exp--; + long mod = value % 5; + value /= 5; + int modDiv = 1; + if (value < Long.MAX_VALUE / (1L << 4)) { + exp -= 4; + value <<= 4; + modDiv <<= 4; + } + if (value < Long.MAX_VALUE / (1L << 2)) { + exp -= 2; + value <<= 2; + modDiv <<= 2; + } + if (value < Long.MAX_VALUE / (1L << 1)) { + exp -= 1; + value <<= 1; + modDiv <<= 1; + } + if (decimalPlaces > 1) + value += modDiv * mod / 5; + else + value += (modDiv * mod + 4) / 5; + } + final double d = Math.scalb((double) value, exp); + return negative ? -d : d; + } } From 9ebd8faba11064066c239d9c973b7ca88c313bbe Mon Sep 17 00:00:00 2001 From: twobiers <22715034+twobiers@users.noreply.github.com> Date: Sat, 30 Dec 2023 11:52:19 +0100 Subject: [PATCH 03/18] collect into a treemap --- .../onebrc/CalculateAverage_twobiers.java | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java b/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java index bab57109d..72a622e29 100644 --- a/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java +++ b/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java @@ -22,7 +22,6 @@ import java.nio.file.Files; import java.nio.file.Paths; import java.util.Arrays; -import java.util.Map; import java.util.Map.Entry; import java.util.TreeMap; import java.util.stream.Collectors; @@ -32,12 +31,16 @@ public class CalculateAverage_twobiers { private static final String FILE = "./measurements.txt"; public static void main(String[] args) throws IOException { - Map measurements = Files.lines(Paths.get(FILE)) + TreeMap measurements = Files.lines(Paths.get(FILE)) .parallel() .map(l -> fastSplit(l)) - .collect(groupingBy(m -> m[0], averagingDouble(m -> fastParseDouble(m[1])))); - - measurements = new TreeMap<>(measurements.entrySet().stream().collect(Collectors.toMap(Entry::getKey, e -> Math.round(e.getValue() * 10.0) / 10.0))); + .collect(groupingBy(m -> m[0], TreeMap::new, averagingDouble(m -> fastParseDouble(m[1])))) + .entrySet().stream() + // Is it possible to combine this collector with the above? + .collect( + Collectors.toMap(Entry::getKey, e -> Math.round(e.getValue() * 10.0) / 10.0, (k, v) -> { + throw new RuntimeException("Should not happen"); + }, TreeMap::new)); System.out.println(measurements); } @@ -65,15 +68,15 @@ private static Double fastParseDouble(String str) { boolean negative = false; int decimalPlaces = Integer.MIN_VALUE; var chars = str.toCharArray(); - for (char c : chars) { - if (c >= '0' && c <= '9') { - value = value * 10 + (c - '0'); + for (char ch : chars) { + if (ch >= '0' && ch <= '9') { + value = value * 10 + (ch - '0'); decimalPlaces++; } - else if (c == '-') { + else if (ch == '-') { negative = true; } - else if (c == '.') { + else if (ch == '.') { decimalPlaces = 0; } } @@ -128,10 +131,12 @@ private static double asDouble(long value, int exp, boolean negative, int decima value <<= 1; modDiv <<= 1; } - if (decimalPlaces > 1) + if (decimalPlaces > 1) { value += modDiv * mod / 5; - else + } + else { value += (modDiv * mod + 4) / 5; + } } final double d = Math.scalb((double) value, exp); return negative ? -d : d; From 929629ef868b42faec1cd9e985903cc725cfffc3 Mon Sep 17 00:00:00 2001 From: twobiers <22715034+twobiers@users.noreply.github.com> Date: Sat, 30 Dec 2023 12:16:08 +0100 Subject: [PATCH 04/18] Tweak JVM options --- calculate_average_twobiers.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/calculate_average_twobiers.sh b/calculate_average_twobiers.sh index e8a688f65..98d62789d 100755 --- a/calculate_average_twobiers.sh +++ b/calculate_average_twobiers.sh @@ -15,6 +15,5 @@ # limitations under the License. # -# TODO: Adjust heap size and GC -JAVA_OPTS="-XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication -XX:+UseLargePages" +JAVA_OPTS="-XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication -XX:+UseTransparentHugePages -XX:+UseZGC -XX:+ZGenerational -Xms16g -Xmx32g" java $JAVA_OPTS --class-path target/average-1.0.0-SNAPSHOT.jar dev.morling.onebrc.CalculateAverage_twobiers From 7de390c829859094e5745666201dd25332bc54f8 Mon Sep 17 00:00:00 2001 From: twobiers <22715034+twobiers@users.noreply.github.com> Date: Sat, 30 Dec 2023 15:25:24 +0100 Subject: [PATCH 05/18] Inline rounding into collector --- .../onebrc/CalculateAverage_twobiers.java | 81 ++++++++++++++++--- 1 file changed, 72 insertions(+), 9 deletions(-) diff --git a/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java b/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java index 72a622e29..a822c9fe8 100644 --- a/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java +++ b/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java @@ -15,32 +15,75 @@ */ package dev.morling.onebrc; -import static java.util.stream.Collectors.averagingDouble; import static java.util.stream.Collectors.groupingBy; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Arrays; -import java.util.Map.Entry; +import java.util.Collections; +import java.util.Set; import java.util.TreeMap; -import java.util.stream.Collectors; +import java.util.function.BiConsumer; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.Collector; public class CalculateAverage_twobiers { private static final String FILE = "./measurements.txt"; + private static final FastAveragingCollector FAST_AVERAGING_COLLECTOR = new FastAveragingCollector(); + // private static final VectorSpecies SPECIES = IntVector.SPECIES_256; + + private static class FastAveragingCollector implements Collector { + @Override + public Supplier supplier() { + return () -> new double[4]; + } + + @Override + public BiConsumer accumulator() { + return (a, t) -> { + double val = fastParseDouble(t[1]); + sumWithCompensation(a, val); + a[2]++; + a[3]+= val; + }; + } + + @Override + public BinaryOperator combiner() { + return (a, b) -> { + sumWithCompensation(a, b[0]); + // Subtract compensation bits + sumWithCompensation(a, -b[1]); + a[2] += b[2]; a[3] += b[3]; + return a; + }; + } + + @Override + public Function finisher() { + return a -> (a[2] == 0) ? 0.0d : Math.round ( (computeFinalSum(a) / a[2]) * 10.0 / 10.0 ); + } + + @Override + public Set characteristics() { + return Collections.emptySet(); + } + } public static void main(String[] args) throws IOException { TreeMap measurements = Files.lines(Paths.get(FILE)) .parallel() .map(l -> fastSplit(l)) - .collect(groupingBy(m -> m[0], TreeMap::new, averagingDouble(m -> fastParseDouble(m[1])))) - .entrySet().stream() - // Is it possible to combine this collector with the above? .collect( - Collectors.toMap(Entry::getKey, e -> Math.round(e.getValue() * 10.0) / 10.0, (k, v) -> { - throw new RuntimeException("Should not happen"); - }, TreeMap::new)); + groupingBy( + m -> m[0], + TreeMap::new, + FAST_AVERAGING_COLLECTOR + )); System.out.println(measurements); } @@ -141,4 +184,24 @@ private static double asDouble(long value, int exp, boolean negative, int decima final double d = Math.scalb((double) value, exp); return negative ? -d : d; } + + private static double[] sumWithCompensation(double[] intermediateSum, double value) { + double tmp = value - intermediateSum[1]; + double sum = intermediateSum[0]; + double velvel = sum + tmp; // Little wolf of rounding error + intermediateSum[1] = (velvel - sum) - tmp; + intermediateSum[0] = velvel; + return intermediateSum; + } + + private static double computeFinalSum(double[] summands) { + // Final sum with better error bounds subtract second summand as it is negated + double tmp = summands[0] - summands[1]; + double simpleSum = summands[summands.length - 1]; + if (Double.isNaN(tmp) && Double.isInfinite(simpleSum)) + return simpleSum; + else + return tmp; + } + } From dac013bbda30ea73503cf21376979ed82e8a7e92 Mon Sep 17 00:00:00 2001 From: twobiers <22715034+twobiers@users.noreply.github.com> Date: Sat, 30 Dec 2023 15:34:44 +0100 Subject: [PATCH 06/18] reduce some operations --- .../morling/onebrc/CalculateAverage_twobiers.java | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java b/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java index a822c9fe8..55bb6acec 100644 --- a/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java +++ b/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java @@ -58,14 +58,15 @@ public BinaryOperator combiner() { sumWithCompensation(a, b[0]); // Subtract compensation bits sumWithCompensation(a, -b[1]); - a[2] += b[2]; a[3] += b[3]; + a[2] += b[2]; + a[3] += b[3]; return a; }; } @Override public Function finisher() { - return a -> (a[2] == 0) ? 0.0d : Math.round ( (computeFinalSum(a) / a[2]) * 10.0 / 10.0 ); + return a -> (a[2] == 0) ? 0.0d : Math.round ( (a[0] + a[1] / a[2]) * 10.0 / 10.0 ); } @Override @@ -194,14 +195,4 @@ private static double[] sumWithCompensation(double[] intermediateSum, double val return intermediateSum; } - private static double computeFinalSum(double[] summands) { - // Final sum with better error bounds subtract second summand as it is negated - double tmp = summands[0] - summands[1]; - double simpleSum = summands[summands.length - 1]; - if (Double.isNaN(tmp) && Double.isInfinite(simpleSum)) - return simpleSum; - else - return tmp; - } - } From 041860874249a7f7996611d33efebcbdbc6a3f72 Mon Sep 17 00:00:00 2001 From: twobiers <22715034+twobiers@users.noreply.github.com> Date: Sat, 30 Dec 2023 15:37:38 +0100 Subject: [PATCH 07/18] oops, add missing braces --- src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java b/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java index 55bb6acec..65bbbb4bf 100644 --- a/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java +++ b/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java @@ -66,7 +66,7 @@ public BinaryOperator combiner() { @Override public Function finisher() { - return a -> (a[2] == 0) ? 0.0d : Math.round ( (a[0] + a[1] / a[2]) * 10.0 / 10.0 ); + return a -> (a[2] == 0) ? 0.0d : Math.round ( ((a[0] + a[1]) / a[2]) * 10.0 / 10.0 ); } @Override From 6b162b2ff84e76eca2d350b1a7d3c51e81916a0c Mon Sep 17 00:00:00 2001 From: twobiers <22715034+twobiers@users.noreply.github.com> Date: Sat, 30 Dec 2023 15:48:05 +0100 Subject: [PATCH 08/18] tweak JVM options --- calculate_average_twobiers.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/calculate_average_twobiers.sh b/calculate_average_twobiers.sh index 98d62789d..84573cd62 100755 --- a/calculate_average_twobiers.sh +++ b/calculate_average_twobiers.sh @@ -15,5 +15,5 @@ # limitations under the License. # -JAVA_OPTS="-XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication -XX:+UseTransparentHugePages -XX:+UseZGC -XX:+ZGenerational -Xms16g -Xmx32g" +JAVA_OPTS="-XX:+UseStringDeduplication -XX:+CompactStrings -XX:+UseTransparentHugePages" java $JAVA_OPTS --class-path target/average-1.0.0-SNAPSHOT.jar dev.morling.onebrc.CalculateAverage_twobiers From fc873216edab0400f65814f841accf14da530ec0 Mon Sep 17 00:00:00 2001 From: twobiers <22715034+twobiers@users.noreply.github.com> Date: Sun, 31 Dec 2023 22:32:32 +0100 Subject: [PATCH 09/18] small fixes --- .../morling/onebrc/CalculateAverage_twobiers.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java b/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java index 65bbbb4bf..6a83b8d95 100644 --- a/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java +++ b/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java @@ -48,7 +48,7 @@ public BiConsumer accumulator() { double val = fastParseDouble(t[1]); sumWithCompensation(a, val); a[2]++; - a[3]+= val; + a[3] += val; }; } @@ -66,7 +66,7 @@ public BinaryOperator combiner() { @Override public Function finisher() { - return a -> (a[2] == 0) ? 0.0d : Math.round ( ((a[0] + a[1]) / a[2]) * 10.0 / 10.0 ); + return a -> (a[2] == 0) ? 0.0d : Math.round(((a[0] + a[1]) / a[2]) * 10.0) / 10.0; } @Override @@ -80,11 +80,10 @@ public static void main(String[] args) throws IOException { .parallel() .map(l -> fastSplit(l)) .collect( - groupingBy( - m -> m[0], - TreeMap::new, - FAST_AVERAGING_COLLECTOR - )); + groupingBy( + m -> m[0], + TreeMap::new, + FAST_AVERAGING_COLLECTOR)); System.out.println(measurements); } From d7023e0396689e134bdc801d77456fd9614b6dc5 Mon Sep 17 00:00:00 2001 From: twobiers <22715034+twobiers@users.noreply.github.com> Date: Mon, 1 Jan 2024 18:29:11 +0100 Subject: [PATCH 10/18] add min and max to processing --- calculate_average_twobiers.sh | 2 +- .../onebrc/CalculateAverage_twobiers.java | 35 ++++++++++++++++--- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/calculate_average_twobiers.sh b/calculate_average_twobiers.sh index 84573cd62..f7ecd84c9 100755 --- a/calculate_average_twobiers.sh +++ b/calculate_average_twobiers.sh @@ -15,5 +15,5 @@ # limitations under the License. # -JAVA_OPTS="-XX:+UseStringDeduplication -XX:+CompactStrings -XX:+UseTransparentHugePages" +JAVA_OPTS="-XX:+UseStringDeduplication -XX:+CompactStrings -XX:+UseTransparentHugePages -da" java $JAVA_OPTS --class-path target/average-1.0.0-SNAPSHOT.jar dev.morling.onebrc.CalculateAverage_twobiers diff --git a/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java b/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java index 6a83b8d95..cc50fe8c3 100644 --- a/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java +++ b/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java @@ -36,10 +36,16 @@ public class CalculateAverage_twobiers { private static final FastAveragingCollector FAST_AVERAGING_COLLECTOR = new FastAveragingCollector(); // private static final VectorSpecies SPECIES = IntVector.SPECIES_256; - private static class FastAveragingCollector implements Collector { + private static class FastAveragingCollector implements Collector { @Override public Supplier supplier() { - return () -> new double[4]; + // 0: summand 1 + // 1: summand 2 + // 2: count + // 3: parsed value + // 4: current max + // 5: current min + return () -> new double[6]; } @Override @@ -49,6 +55,12 @@ public BiConsumer accumulator() { sumWithCompensation(a, val); a[2]++; a[3] += val; + if (val > a[4]) { + a[4] = val; + } + if(val < a[5]) { + a[5] = val; + } }; } @@ -60,13 +72,24 @@ public BinaryOperator combiner() { sumWithCompensation(a, -b[1]); a[2] += b[2]; a[3] += b[3]; + if (b[4] > a[4]) { + a[4] = b[4]; + } + if(a[5] < b[5]) { + a[5] = b[5]; + } return a; }; } @Override - public Function finisher() { - return a -> (a[2] == 0) ? 0.0d : Math.round(((a[0] + a[1]) / a[2]) * 10.0) / 10.0; + public Function finisher() { + return a -> { + var mean = (a[2] == 0) ? 0.0d : Math.round(((a[0] + a[1]) / a[2]) * 10.0) / 10.0; + var max = a[4]; + var min = a[5]; + return min + "/" + mean + "/" + max; + }; } @Override @@ -76,7 +99,7 @@ public Set characteristics() { } public static void main(String[] args) throws IOException { - TreeMap measurements = Files.lines(Paths.get(FILE)) + TreeMap measurements = Files.lines(Paths.get(FILE)) .parallel() .map(l -> fastSplit(l)) .collect( @@ -86,6 +109,8 @@ public static void main(String[] args) throws IOException { FAST_AVERAGING_COLLECTOR)); System.out.println(measurements); + // Simple test for my generated file + assert measurements.toString().equals("{Abha=-26.9/18.0/61.8, Abidjan=-23.3/26.0/71.5, Abéché=-19.4/29.4/72.3, Accra=-20.5/26.4/69.9, Addis Ababa=-29.5/16.0/62.3, Adelaide=-26.8/17.3/66.2, Aden=-14.8/29.1/76.1, Ahvaz=-20.7/25.4/70.3, Albuquerque=-33.5/14.0/56.9, Alexandra=-32.5/11.0/63.1, Alexandria=-26.7/20.0/62.5, Algiers=-30.7/18.2/63.5, Alice Springs=-27.6/21.0/66.7, Almaty=-35.9/10.0/53.7, Amsterdam=-34.9/10.2/55.0, Anadyr=-50.7/-6.9/42.5, Anchorage=-47.1/2.8/47.0, Andorra la Vella=-34.3/9.8/56.1, Ankara=-31.6/12.0/63.8, Antananarivo=-32.2/17.9/63.7, Antsiranana=-22.1/25.2/67.8, Arkhangelsk=-46.2/1.3/46.7, Ashgabat=-29.0/17.1/62.1, Asmara=-29.3/15.6/59.3, Assab=-14.5/30.5/76.5, Astana=-40.9/3.5/48.2, Athens=-29.2/19.2/61.6, Atlanta=-28.2/17.0/62.5, Auckland=-28.9/15.2/59.3, Austin=-23.4/20.7/63.5, Baghdad=-29.5/22.8/68.7, Baguio=-24.5/19.5/60.7, Baku=-27.7/15.1/59.7, Baltimore=-30.8/13.1/60.9, Bamako=-20.5/27.8/73.7, Bangkok=-18.6/28.6/75.1, Bangui=-21.1/26.0/71.6, Banjul=-18.0/26.0/70.5, Barcelona=-27.1/18.2/72.3, Bata=-30.7/25.1/69.2, Batumi=-30.6/14.0/59.2, Beijing=-32.4/12.9/55.0, Beirut=-24.7/20.9/67.3, Belgrade=-34.9/12.5/55.0, Belize City=-18.3/26.7/72.4, Benghazi=-27.4/19.9/65.6, Bergen=-35.2/7.7/51.9, Berlin=-38.5/10.3/59.7, Bilbao=-28.6/14.7/58.7, Birao=-23.7/26.5/73.5, Bishkek=-36.9/11.3/59.1, Bissau=-15.1/27.0/72.7, Blantyre=-25.4/22.2/75.5, Bloemfontein=-34.1/15.6/57.5, Boise=-34.6/11.4/60.5, Bordeaux=-29.9/14.2/57.0, Bosaso=-16.8/30.0/73.8, Boston=-32.7/10.9/56.2, Bouaké=-16.0/26.0/71.0, Bratislava=-32.3/10.5/55.6, Brazzaville=-19.3/25.0/70.8, Bridgetown=-16.3/27.0/70.4, Brisbane=-23.0/21.4/69.2, Brussels=-34.8/10.5/52.6, Bucharest=-30.0/10.8/56.4, Budapest=-36.4/11.3/54.6, Bujumbura=-24.3/23.8/69.5, Bulawayo=-23.5/18.9/60.7, Burnie=-32.2/13.0/57.4, Busan=-35.9/15.0/57.9, Cabo San Lucas=-18.4/23.9/67.8, Cairns=-18.9/25.0/69.6, Cairo=-28.0/21.4/64.9, Calgary=-41.2/4.4/51.4, Canberra=-28.6/13.1/56.3, Cape Town=-29.8/16.2/58.9, Changsha=-27.3/17.4/60.3, Charlotte=-29.6/16.1/60.9, Chiang Mai=-20.8/25.8/70.0, Chicago=-35.2/9.8/59.5, Chihuahua=-34.0/18.6/63.3, Chittagong=-19.8/25.9/74.8, Chișinău=-30.7/10.2/54.8, Chongqing=-24.6/18.6/66.6, Christchurch=-32.6/12.2/59.0, City of San Marino=-36.9/11.8/63.4, Colombo=-16.2/27.4/71.4, Columbus=-32.4/11.7/62.0, Conakry=-17.9/26.4/71.4, Copenhagen=-38.2/9.1/65.3, Cotonou=-19.8/27.2/73.2, Cracow=-33.4/9.3/58.5, Da Lat=-23.8/17.9/61.2, Da Nang=-19.2/25.8/70.1, Dakar=-20.7/24.0/68.6, Dallas=-25.3/18.9/63.5, Damascus=-28.4/17.0/63.7, Dampier=-18.6/26.4/70.2, Dar es Salaam=-17.7/25.8/69.2, Darwin=-14.5/27.6/74.8, Denpasar=-21.6/23.7/68.4, Denver=-32.1/10.4/59.0, Detroit=-36.8/10.0/56.6, Dhaka=-19.2/25.9/70.7, Dikson=-54.4/-11.1/37.8, Dili=-18.3/26.6/71.0, Djibouti=-18.2/29.9/76.6, Dodoma=-23.2/22.7/68.4, Dolisie=-20.9/24.0/66.2, Douala=-15.9/26.7/72.4, Dubai=-17.8/26.9/71.2, Dublin=-38.7/9.8/56.8, Dunedin=-35.2/11.1/55.4, Durban=-21.5/20.6/65.6, Dushanbe=-26.9/14.7/59.7, Edinburgh=-33.0/9.3/54.2, Edmonton=-38.9/4.2/48.5, El Paso=-24.3/18.1/63.7, Entebbe=-24.5/21.0/68.1, Erbil=-25.8/19.5/65.9, Erzurum=-38.8/5.1/49.0, Fairbanks=-47.4/-2.3/44.2, Fianarantsoa=-26.8/17.9/63.1, Flores, Petén=-21.1/26.4/73.4, Frankfurt=-35.6/10.6/56.2, Fresno=-23.9/17.9/67.4, Fukuoka=-28.0/17.0/62.0, Gaborone=-25.2/21.0/64.9, Gabès=-30.0/19.5/64.7, Gagnoa=-19.2/26.0/72.1, Gangtok=-33.3/15.2/63.1, Garissa=-19.4/29.3/83.4, Garoua=-16.4/28.3/80.1, George Town=-16.6/27.9/71.3, Ghanzi=-22.4/21.4/64.0, Gjoa Haven=-63.9/-14.4/30.8, Guadalajara=-22.7/20.9/69.1, Guangzhou=-34.0/22.4/69.4, Guatemala City=-26.7/20.4/63.4, Halifax=-35.5/7.5/50.5, Hamburg=-36.2/9.7/57.3, Hamilton=-28.9/13.8/58.9, Hanga Roa=-22.8/20.5/66.6, Hanoi=-20.2/23.6/70.3, Harare=-25.5/18.4/61.5, Harbin=-43.4/5.0/50.3, Hargeisa=-21.6/21.7/71.2, Hat Yai=-17.0/27.0/70.6, Havana=-28.3/25.2/74.0, Helsinki=-38.7/5.9/55.5, Heraklion=-25.4/18.9/64.9, Hiroshima=-28.7/16.3/60.7, Ho Chi Minh City=-21.3/27.4/69.2, Hobart=-34.4/12.7/60.7, Hong Kong=-23.9/23.3/66.6, Honiara=-17.9/26.5/72.1, Honolulu=-20.9/25.4/75.6, Houston=-28.3/20.8/64.4, Ifrane=-31.0/11.4/56.1, Indianapolis=-35.1/11.8/58.0, Iqaluit=-61.8/-9.3/38.7, Irkutsk=-49.6/1.0/46.7, Istanbul=-31.6/13.9/68.0, Jacksonville=-21.9/20.3/65.3, Jakarta=-18.2/26.7/74.0, Jayapura=-15.5/27.0/70.6, Jerusalem=-25.4/18.3/70.5, Johannesburg=-29.2/15.5/58.5, Jos=-22.4/22.8/66.3, Juba=-17.1/27.8/69.5, Kabul=-29.6/12.1/59.8, Kampala=-26.0/20.0/66.3, Kandi=-17.3/27.7/74.9, Kankan=-20.0/26.5/74.1, Kano=-20.0/26.4/69.8, Kansas City=-32.9/12.5/58.3, Karachi=-21.6/26.0/71.6, Karonga=-21.0/24.3/71.6, Kathmandu=-27.7/18.3/62.5, Khartoum=-20.3/29.9/78.0, Kingston=-17.6/27.4/69.9, Kinshasa=-22.6/25.3/70.1, Kolkata=-14.8/26.7/71.8, Kuala Lumpur=-17.6/27.3/73.1, Kumasi=-19.2/25.9/75.1, Kunming=-32.0/15.7/58.5, Kuopio=-45.8/3.4/46.5, Kuwait City=-19.2/25.7/71.2, Kyiv=-37.8/8.4/55.1, Kyoto=-27.2/15.8/64.9, La Ceiba=-17.8/26.2/72.7, La Paz=-23.7/23.7/66.4, Lagos=-16.6/26.8/74.6, Lahore=-19.8/24.3/70.3, Lake Havasu City=-24.8/23.7/68.3, Lake Tekapo=-36.3/8.7/54.1, Las Palmas de Gran Canaria=-29.4/21.2/66.7, Las Vegas=-24.9/20.3/64.8, Launceston=-32.0/13.1/57.2, Lhasa=-38.8/7.6/52.9, Libreville=-21.5/25.9/71.7, Lisbon=-34.9/17.5/65.6, Livingstone=-23.9/21.8/65.5, Ljubljana=-30.3/10.9/57.1, Lodwar=-14.8/29.3/73.1, Lomé=-17.5/26.9/70.7, London=-34.8/11.3/55.7, Los Angeles=-30.7/18.6/62.6, Louisville=-32.1/13.9/62.9, Luanda=-17.6/25.8/72.3, Lubumbashi=-26.0/20.8/66.9, Lusaka=-23.8/19.9/62.1, Luxembourg City=-33.0/9.3/56.0, Lviv=-36.1/7.8/51.7, Lyon=-36.7/12.5/56.8, Madrid=-30.4/15.0/59.1, Mahajanga=-17.2/26.3/67.9, Makassar=-14.9/26.7/73.1, Makurdi=-23.8/26.0/69.2, Malabo=-20.5/26.3/71.7, Malé=-21.6/28.0/75.4, Managua=-29.5/27.3/74.3, Manama=-20.3/26.5/72.8, Mandalay=-15.3/28.0/73.1, Mango=-14.7/28.1/74.5, Manila=-18.1/28.4/72.1, Maputo=-22.2/22.8/70.5, Marrakesh=-27.6/19.6/71.3, Marseille=-29.7/15.8/60.7, Maun=-21.5/22.4/65.6, Medan=-18.2/26.5/69.2, Mek'ele=-29.0/22.7/69.3, Melbourne=-29.6/15.1/64.2, Memphis=-27.3/17.2/61.6, Mexicali=-24.4/23.1/71.6, Mexico City=-27.1/17.5/63.1, Miami=-18.7/24.9/71.4, Milan=-32.9/13.0/59.2, Milwaukee=-33.9/8.9/55.1, Minneapolis=-35.5/7.8/50.9, Minsk=-35.2/6.8/53.5, Mogadishu=-18.6/27.1/73.9, Mombasa=-17.3/26.3/72.9, Monaco=-36.0/16.4/64.7, Moncton=-38.9/6.1/49.2, Monterrey=-20.0/22.3/66.4, Montreal=-41.5/6.8/53.1, Moscow=-40.5/5.8/50.6, Mumbai=-19.7/27.1/70.7, Murmansk=-47.6/0.6/49.6, Muscat=-16.9/28.0/78.6, Mzuzu=-25.7/17.7/60.6, N'Djamena=-15.5/28.3/71.7, Naha=-22.1/23.1/75.7, Nairobi=-29.7/17.8/60.1, Nakhon Ratchasima=-17.3/27.3/79.0, Napier=-33.7/14.6/58.0, Napoli=-25.7/15.9/61.1, Nashville=-33.2/15.4/59.1, Nassau=-20.4/24.6/67.9, Ndola=-23.4/20.3/64.5, New Delhi=-19.6/25.0/70.1, New Orleans=-24.3/20.7/64.5, New York City=-32.1/12.9/60.8, Ngaoundéré=-26.7/22.0/64.6, Niamey=-18.9/29.3/73.3, Nicosia=-27.2/19.7/64.8, Niigata=-29.8/13.9/60.0, Nouadhibou=-24.4/21.3/65.7, Nouakchott=-22.2/25.7/71.2, Novosibirsk=-40.9/1.7/45.7, Nuuk=-47.0/-1.4/48.1, Odesa=-41.9/10.7/53.1, Odienné=-25.7/26.0/70.0, Oklahoma City=-25.9/15.9/59.8, Omaha=-37.7/10.6/56.4, Oranjestad=-14.4/28.1/70.7, Oslo=-38.9/5.7/54.5, Ottawa=-39.2/6.6/48.7, Ouagadougou=-16.9/28.3/75.4, Ouahigouya=-15.7/28.6/75.0, Ouarzazate=-27.6/18.9/62.1, Oulu=-42.3/2.7/45.1, Palembang=-19.7/27.3/71.1, Palermo=-27.2/18.5/63.0, Palm Springs=-26.7/24.5/73.4, Palmerston North=-36.3/13.2/56.0, Panama City=-19.2/28.0/76.6, Parakou=-16.4/26.8/69.9, Paris=-33.4/12.3/57.6, Perth=-28.3/18.7/67.7, Petropavlovsk-Kamchatsky=-41.7/1.9/49.3, Philadelphia=-32.9/13.2/59.4, Phnom Penh=-15.2/28.3/73.5, Phoenix=-18.7/23.9/69.1, Pittsburgh=-38.1/10.8/57.1, Podgorica=-32.2/15.3/58.9, Pointe-Noire=-20.8/26.1/70.7, Pontianak=-18.5/27.7/75.5, Port Moresby=-16.6/26.9/69.7, Port Sudan=-12.9/28.4/75.4, Port Vila=-20.4/24.3/71.3, Port-Gentil=-16.6/26.0/74.4, Portland (OR)=-31.7/12.4/60.2, Porto=-29.1/15.7/57.6, Prague=-41.1/8.4/54.7, Praia=-21.5/24.4/70.7, Pretoria=-26.5/18.2/64.6, Pyongyang=-32.6/10.8/55.7, Rabat=-28.3/17.2/61.1, Rangpur=-19.4/24.4/67.5, Reggane=-19.0/28.3/70.8, Reykjavík=-41.3/4.3/47.3, Riga=-41.8/6.2/54.3, Riyadh=-26.1/26.1/69.6, Rome=-27.6/15.2/58.4, Roseau=-23.1/26.2/67.8, Rostov-on-Don=-34.0/9.9/58.3, Sacramento=-31.3/16.3/59.9, Saint Petersburg=-37.5/5.8/48.8, Saint-Pierre=-39.5/5.7/49.8, Salt Lake City=-35.6/11.6/55.5, San Antonio=-28.7/20.8/66.1, San Diego=-26.0/17.8/67.9, San Francisco=-28.4/14.6/64.1, San Jose=-25.6/16.4/58.4, San José=-20.7/22.6/67.3, San Juan=-15.3/27.2/72.2, San Salvador=-20.9/23.1/65.7, Sana'a=-28.1/20.0/65.4, Santo Domingo=-19.2/25.9/70.6, Sapporo=-36.1/8.9/54.1, Sarajevo=-42.5/10.1/62.6, Saskatoon=-42.5/3.3/49.9, Seattle=-34.8/11.3/56.1, Seoul=-30.7/12.5/58.2, Seville=-22.1/19.1/64.5, Shanghai=-25.4/16.7/68.4, Singapore=-19.2/27.0/74.2, Skopje=-33.3/12.4/57.6, Sochi=-29.8/14.2/62.2, Sofia=-35.1/10.6/53.6, Sokoto=-19.1/28.0/75.1, Split=-26.8/16.1/61.5, St. John's=-38.6/5.0/51.1, St. Louis=-27.3/13.9/61.6, Stockholm=-35.5/6.6/50.0, Surabaya=-15.5/27.1/76.1, Suva=-19.2/25.6/70.5, Suwałki=-40.9/7.2/50.1, Sydney=-28.0/17.6/69.6, Ségou=-23.0/28.0/73.0, Tabora=-24.6/23.0/71.2, Tabriz=-31.8/12.6/57.8, Taipei=-19.9/23.0/70.7, Tallinn=-36.7/6.4/51.4, Tamale=-16.7/27.9/75.9, Tamanrasset=-24.8/21.7/69.0, Tampa=-25.2/22.9/71.6, Tashkent=-31.2/14.8/65.3, Tauranga=-35.5/14.8/62.8, Tbilisi=-32.4/12.9/59.3, Tegucigalpa=-25.5/21.7/66.8, Tehran=-28.7/17.0/61.7, Tel Aviv=-24.3/20.0/64.7, Thessaloniki=-29.7/16.0/62.1, Thiès=-22.4/24.0/70.6, Tijuana=-25.8/17.8/64.8, Timbuktu=-15.3/28.0/80.0, Tirana=-34.3/15.2/61.9, Toamasina=-20.1/23.4/67.4, Tokyo=-33.6/15.4/60.6, Toliara=-24.5/24.1/74.4, Toluca=-31.6/12.4/58.0, Toronto=-37.2/9.4/51.9, Tripoli=-27.3/20.0/63.1, Tromsø=-40.8/2.9/48.1, Tucson=-25.6/20.9/62.6, Tunis=-24.6/18.4/60.0, Ulaanbaatar=-48.7/-0.4/46.3, Upington=-22.3/20.4/63.2, Vaduz=-37.0/10.1/55.8, Valencia=-25.9/18.3/68.5, Valletta=-25.2/18.8/66.4, Vancouver=-35.2/10.4/53.4, Veracruz=-22.5/25.4/67.7, Vienna=-33.4/10.4/55.0, Vientiane=-21.2/25.9/69.2, Villahermosa=-15.2/27.1/73.3, Vilnius=-40.0/6.0/52.7, Virginia Beach=-28.8/15.8/59.9, Vladivostok=-39.0/4.9/49.3, Warsaw=-34.0/8.5/53.5, Washington, D.C.=-30.2/14.6/59.8, Wau=-17.4/27.8/70.2, Wellington=-31.0/12.9/59.2, Whitehorse=-50.4/-0.1/46.7, Wichita=-29.7/13.9/60.1, Willemstad=-19.1/28.0/73.5, Winnipeg=-39.3/3.0/53.5, Wrocław=-41.4/9.6/53.7, Xi'an=-31.9/14.1/57.2, Yakutsk=-54.0/-8.8/33.5, Yangon=-19.6/27.5/76.4, Yaoundé=-23.8/23.8/69.9, Yellowknife=-55.5/-4.3/38.6, Yerevan=-30.0/12.4/61.0, Yinchuan=-36.8/9.0/53.4, Zagreb=-36.3/10.7/56.9, Zanzibar City=-20.4/26.0/71.5, Zürich=-36.0/9.3/56.3, Ürümqi=-40.5/7.4/54.5, İzmir=-29.5/17.9/61.2}"); } private static String[] fastSplit(String str) { From be09e50fb48ce3bb46b87846c8b9454cc142808e Mon Sep 17 00:00:00 2001 From: twobiers <22715034+twobiers@users.noreply.github.com> Date: Mon, 1 Jan 2024 19:00:35 +0100 Subject: [PATCH 11/18] fix min --- .../dev/morling/onebrc/CalculateAverage_twobiers.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java b/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java index cc50fe8c3..26abcf44a 100644 --- a/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java +++ b/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java @@ -58,7 +58,7 @@ public BiConsumer accumulator() { if (val > a[4]) { a[4] = val; } - if(val < a[5]) { + if (val < a[5]) { a[5] = val; } }; @@ -75,7 +75,7 @@ public BinaryOperator combiner() { if (b[4] > a[4]) { a[4] = b[4]; } - if(a[5] < b[5]) { + if (b[5] < a[5]) { a[5] = b[5]; } return a; @@ -109,8 +109,10 @@ public static void main(String[] args) throws IOException { FAST_AVERAGING_COLLECTOR)); System.out.println(measurements); + // Simple test for my generated file - assert measurements.toString().equals("{Abha=-26.9/18.0/61.8, Abidjan=-23.3/26.0/71.5, Abéché=-19.4/29.4/72.3, Accra=-20.5/26.4/69.9, Addis Ababa=-29.5/16.0/62.3, Adelaide=-26.8/17.3/66.2, Aden=-14.8/29.1/76.1, Ahvaz=-20.7/25.4/70.3, Albuquerque=-33.5/14.0/56.9, Alexandra=-32.5/11.0/63.1, Alexandria=-26.7/20.0/62.5, Algiers=-30.7/18.2/63.5, Alice Springs=-27.6/21.0/66.7, Almaty=-35.9/10.0/53.7, Amsterdam=-34.9/10.2/55.0, Anadyr=-50.7/-6.9/42.5, Anchorage=-47.1/2.8/47.0, Andorra la Vella=-34.3/9.8/56.1, Ankara=-31.6/12.0/63.8, Antananarivo=-32.2/17.9/63.7, Antsiranana=-22.1/25.2/67.8, Arkhangelsk=-46.2/1.3/46.7, Ashgabat=-29.0/17.1/62.1, Asmara=-29.3/15.6/59.3, Assab=-14.5/30.5/76.5, Astana=-40.9/3.5/48.2, Athens=-29.2/19.2/61.6, Atlanta=-28.2/17.0/62.5, Auckland=-28.9/15.2/59.3, Austin=-23.4/20.7/63.5, Baghdad=-29.5/22.8/68.7, Baguio=-24.5/19.5/60.7, Baku=-27.7/15.1/59.7, Baltimore=-30.8/13.1/60.9, Bamako=-20.5/27.8/73.7, Bangkok=-18.6/28.6/75.1, Bangui=-21.1/26.0/71.6, Banjul=-18.0/26.0/70.5, Barcelona=-27.1/18.2/72.3, Bata=-30.7/25.1/69.2, Batumi=-30.6/14.0/59.2, Beijing=-32.4/12.9/55.0, Beirut=-24.7/20.9/67.3, Belgrade=-34.9/12.5/55.0, Belize City=-18.3/26.7/72.4, Benghazi=-27.4/19.9/65.6, Bergen=-35.2/7.7/51.9, Berlin=-38.5/10.3/59.7, Bilbao=-28.6/14.7/58.7, Birao=-23.7/26.5/73.5, Bishkek=-36.9/11.3/59.1, Bissau=-15.1/27.0/72.7, Blantyre=-25.4/22.2/75.5, Bloemfontein=-34.1/15.6/57.5, Boise=-34.6/11.4/60.5, Bordeaux=-29.9/14.2/57.0, Bosaso=-16.8/30.0/73.8, Boston=-32.7/10.9/56.2, Bouaké=-16.0/26.0/71.0, Bratislava=-32.3/10.5/55.6, Brazzaville=-19.3/25.0/70.8, Bridgetown=-16.3/27.0/70.4, Brisbane=-23.0/21.4/69.2, Brussels=-34.8/10.5/52.6, Bucharest=-30.0/10.8/56.4, Budapest=-36.4/11.3/54.6, Bujumbura=-24.3/23.8/69.5, Bulawayo=-23.5/18.9/60.7, Burnie=-32.2/13.0/57.4, Busan=-35.9/15.0/57.9, Cabo San Lucas=-18.4/23.9/67.8, Cairns=-18.9/25.0/69.6, Cairo=-28.0/21.4/64.9, Calgary=-41.2/4.4/51.4, Canberra=-28.6/13.1/56.3, Cape Town=-29.8/16.2/58.9, Changsha=-27.3/17.4/60.3, Charlotte=-29.6/16.1/60.9, Chiang Mai=-20.8/25.8/70.0, Chicago=-35.2/9.8/59.5, Chihuahua=-34.0/18.6/63.3, Chittagong=-19.8/25.9/74.8, Chișinău=-30.7/10.2/54.8, Chongqing=-24.6/18.6/66.6, Christchurch=-32.6/12.2/59.0, City of San Marino=-36.9/11.8/63.4, Colombo=-16.2/27.4/71.4, Columbus=-32.4/11.7/62.0, Conakry=-17.9/26.4/71.4, Copenhagen=-38.2/9.1/65.3, Cotonou=-19.8/27.2/73.2, Cracow=-33.4/9.3/58.5, Da Lat=-23.8/17.9/61.2, Da Nang=-19.2/25.8/70.1, Dakar=-20.7/24.0/68.6, Dallas=-25.3/18.9/63.5, Damascus=-28.4/17.0/63.7, Dampier=-18.6/26.4/70.2, Dar es Salaam=-17.7/25.8/69.2, Darwin=-14.5/27.6/74.8, Denpasar=-21.6/23.7/68.4, Denver=-32.1/10.4/59.0, Detroit=-36.8/10.0/56.6, Dhaka=-19.2/25.9/70.7, Dikson=-54.4/-11.1/37.8, Dili=-18.3/26.6/71.0, Djibouti=-18.2/29.9/76.6, Dodoma=-23.2/22.7/68.4, Dolisie=-20.9/24.0/66.2, Douala=-15.9/26.7/72.4, Dubai=-17.8/26.9/71.2, Dublin=-38.7/9.8/56.8, Dunedin=-35.2/11.1/55.4, Durban=-21.5/20.6/65.6, Dushanbe=-26.9/14.7/59.7, Edinburgh=-33.0/9.3/54.2, Edmonton=-38.9/4.2/48.5, El Paso=-24.3/18.1/63.7, Entebbe=-24.5/21.0/68.1, Erbil=-25.8/19.5/65.9, Erzurum=-38.8/5.1/49.0, Fairbanks=-47.4/-2.3/44.2, Fianarantsoa=-26.8/17.9/63.1, Flores, Petén=-21.1/26.4/73.4, Frankfurt=-35.6/10.6/56.2, Fresno=-23.9/17.9/67.4, Fukuoka=-28.0/17.0/62.0, Gaborone=-25.2/21.0/64.9, Gabès=-30.0/19.5/64.7, Gagnoa=-19.2/26.0/72.1, Gangtok=-33.3/15.2/63.1, Garissa=-19.4/29.3/83.4, Garoua=-16.4/28.3/80.1, George Town=-16.6/27.9/71.3, Ghanzi=-22.4/21.4/64.0, Gjoa Haven=-63.9/-14.4/30.8, Guadalajara=-22.7/20.9/69.1, Guangzhou=-34.0/22.4/69.4, Guatemala City=-26.7/20.4/63.4, Halifax=-35.5/7.5/50.5, Hamburg=-36.2/9.7/57.3, Hamilton=-28.9/13.8/58.9, Hanga Roa=-22.8/20.5/66.6, Hanoi=-20.2/23.6/70.3, Harare=-25.5/18.4/61.5, Harbin=-43.4/5.0/50.3, Hargeisa=-21.6/21.7/71.2, Hat Yai=-17.0/27.0/70.6, Havana=-28.3/25.2/74.0, Helsinki=-38.7/5.9/55.5, Heraklion=-25.4/18.9/64.9, Hiroshima=-28.7/16.3/60.7, Ho Chi Minh City=-21.3/27.4/69.2, Hobart=-34.4/12.7/60.7, Hong Kong=-23.9/23.3/66.6, Honiara=-17.9/26.5/72.1, Honolulu=-20.9/25.4/75.6, Houston=-28.3/20.8/64.4, Ifrane=-31.0/11.4/56.1, Indianapolis=-35.1/11.8/58.0, Iqaluit=-61.8/-9.3/38.7, Irkutsk=-49.6/1.0/46.7, Istanbul=-31.6/13.9/68.0, Jacksonville=-21.9/20.3/65.3, Jakarta=-18.2/26.7/74.0, Jayapura=-15.5/27.0/70.6, Jerusalem=-25.4/18.3/70.5, Johannesburg=-29.2/15.5/58.5, Jos=-22.4/22.8/66.3, Juba=-17.1/27.8/69.5, Kabul=-29.6/12.1/59.8, Kampala=-26.0/20.0/66.3, Kandi=-17.3/27.7/74.9, Kankan=-20.0/26.5/74.1, Kano=-20.0/26.4/69.8, Kansas City=-32.9/12.5/58.3, Karachi=-21.6/26.0/71.6, Karonga=-21.0/24.3/71.6, Kathmandu=-27.7/18.3/62.5, Khartoum=-20.3/29.9/78.0, Kingston=-17.6/27.4/69.9, Kinshasa=-22.6/25.3/70.1, Kolkata=-14.8/26.7/71.8, Kuala Lumpur=-17.6/27.3/73.1, Kumasi=-19.2/25.9/75.1, Kunming=-32.0/15.7/58.5, Kuopio=-45.8/3.4/46.5, Kuwait City=-19.2/25.7/71.2, Kyiv=-37.8/8.4/55.1, Kyoto=-27.2/15.8/64.9, La Ceiba=-17.8/26.2/72.7, La Paz=-23.7/23.7/66.4, Lagos=-16.6/26.8/74.6, Lahore=-19.8/24.3/70.3, Lake Havasu City=-24.8/23.7/68.3, Lake Tekapo=-36.3/8.7/54.1, Las Palmas de Gran Canaria=-29.4/21.2/66.7, Las Vegas=-24.9/20.3/64.8, Launceston=-32.0/13.1/57.2, Lhasa=-38.8/7.6/52.9, Libreville=-21.5/25.9/71.7, Lisbon=-34.9/17.5/65.6, Livingstone=-23.9/21.8/65.5, Ljubljana=-30.3/10.9/57.1, Lodwar=-14.8/29.3/73.1, Lomé=-17.5/26.9/70.7, London=-34.8/11.3/55.7, Los Angeles=-30.7/18.6/62.6, Louisville=-32.1/13.9/62.9, Luanda=-17.6/25.8/72.3, Lubumbashi=-26.0/20.8/66.9, Lusaka=-23.8/19.9/62.1, Luxembourg City=-33.0/9.3/56.0, Lviv=-36.1/7.8/51.7, Lyon=-36.7/12.5/56.8, Madrid=-30.4/15.0/59.1, Mahajanga=-17.2/26.3/67.9, Makassar=-14.9/26.7/73.1, Makurdi=-23.8/26.0/69.2, Malabo=-20.5/26.3/71.7, Malé=-21.6/28.0/75.4, Managua=-29.5/27.3/74.3, Manama=-20.3/26.5/72.8, Mandalay=-15.3/28.0/73.1, Mango=-14.7/28.1/74.5, Manila=-18.1/28.4/72.1, Maputo=-22.2/22.8/70.5, Marrakesh=-27.6/19.6/71.3, Marseille=-29.7/15.8/60.7, Maun=-21.5/22.4/65.6, Medan=-18.2/26.5/69.2, Mek'ele=-29.0/22.7/69.3, Melbourne=-29.6/15.1/64.2, Memphis=-27.3/17.2/61.6, Mexicali=-24.4/23.1/71.6, Mexico City=-27.1/17.5/63.1, Miami=-18.7/24.9/71.4, Milan=-32.9/13.0/59.2, Milwaukee=-33.9/8.9/55.1, Minneapolis=-35.5/7.8/50.9, Minsk=-35.2/6.8/53.5, Mogadishu=-18.6/27.1/73.9, Mombasa=-17.3/26.3/72.9, Monaco=-36.0/16.4/64.7, Moncton=-38.9/6.1/49.2, Monterrey=-20.0/22.3/66.4, Montreal=-41.5/6.8/53.1, Moscow=-40.5/5.8/50.6, Mumbai=-19.7/27.1/70.7, Murmansk=-47.6/0.6/49.6, Muscat=-16.9/28.0/78.6, Mzuzu=-25.7/17.7/60.6, N'Djamena=-15.5/28.3/71.7, Naha=-22.1/23.1/75.7, Nairobi=-29.7/17.8/60.1, Nakhon Ratchasima=-17.3/27.3/79.0, Napier=-33.7/14.6/58.0, Napoli=-25.7/15.9/61.1, Nashville=-33.2/15.4/59.1, Nassau=-20.4/24.6/67.9, Ndola=-23.4/20.3/64.5, New Delhi=-19.6/25.0/70.1, New Orleans=-24.3/20.7/64.5, New York City=-32.1/12.9/60.8, Ngaoundéré=-26.7/22.0/64.6, Niamey=-18.9/29.3/73.3, Nicosia=-27.2/19.7/64.8, Niigata=-29.8/13.9/60.0, Nouadhibou=-24.4/21.3/65.7, Nouakchott=-22.2/25.7/71.2, Novosibirsk=-40.9/1.7/45.7, Nuuk=-47.0/-1.4/48.1, Odesa=-41.9/10.7/53.1, Odienné=-25.7/26.0/70.0, Oklahoma City=-25.9/15.9/59.8, Omaha=-37.7/10.6/56.4, Oranjestad=-14.4/28.1/70.7, Oslo=-38.9/5.7/54.5, Ottawa=-39.2/6.6/48.7, Ouagadougou=-16.9/28.3/75.4, Ouahigouya=-15.7/28.6/75.0, Ouarzazate=-27.6/18.9/62.1, Oulu=-42.3/2.7/45.1, Palembang=-19.7/27.3/71.1, Palermo=-27.2/18.5/63.0, Palm Springs=-26.7/24.5/73.4, Palmerston North=-36.3/13.2/56.0, Panama City=-19.2/28.0/76.6, Parakou=-16.4/26.8/69.9, Paris=-33.4/12.3/57.6, Perth=-28.3/18.7/67.7, Petropavlovsk-Kamchatsky=-41.7/1.9/49.3, Philadelphia=-32.9/13.2/59.4, Phnom Penh=-15.2/28.3/73.5, Phoenix=-18.7/23.9/69.1, Pittsburgh=-38.1/10.8/57.1, Podgorica=-32.2/15.3/58.9, Pointe-Noire=-20.8/26.1/70.7, Pontianak=-18.5/27.7/75.5, Port Moresby=-16.6/26.9/69.7, Port Sudan=-12.9/28.4/75.4, Port Vila=-20.4/24.3/71.3, Port-Gentil=-16.6/26.0/74.4, Portland (OR)=-31.7/12.4/60.2, Porto=-29.1/15.7/57.6, Prague=-41.1/8.4/54.7, Praia=-21.5/24.4/70.7, Pretoria=-26.5/18.2/64.6, Pyongyang=-32.6/10.8/55.7, Rabat=-28.3/17.2/61.1, Rangpur=-19.4/24.4/67.5, Reggane=-19.0/28.3/70.8, Reykjavík=-41.3/4.3/47.3, Riga=-41.8/6.2/54.3, Riyadh=-26.1/26.1/69.6, Rome=-27.6/15.2/58.4, Roseau=-23.1/26.2/67.8, Rostov-on-Don=-34.0/9.9/58.3, Sacramento=-31.3/16.3/59.9, Saint Petersburg=-37.5/5.8/48.8, Saint-Pierre=-39.5/5.7/49.8, Salt Lake City=-35.6/11.6/55.5, San Antonio=-28.7/20.8/66.1, San Diego=-26.0/17.8/67.9, San Francisco=-28.4/14.6/64.1, San Jose=-25.6/16.4/58.4, San José=-20.7/22.6/67.3, San Juan=-15.3/27.2/72.2, San Salvador=-20.9/23.1/65.7, Sana'a=-28.1/20.0/65.4, Santo Domingo=-19.2/25.9/70.6, Sapporo=-36.1/8.9/54.1, Sarajevo=-42.5/10.1/62.6, Saskatoon=-42.5/3.3/49.9, Seattle=-34.8/11.3/56.1, Seoul=-30.7/12.5/58.2, Seville=-22.1/19.1/64.5, Shanghai=-25.4/16.7/68.4, Singapore=-19.2/27.0/74.2, Skopje=-33.3/12.4/57.6, Sochi=-29.8/14.2/62.2, Sofia=-35.1/10.6/53.6, Sokoto=-19.1/28.0/75.1, Split=-26.8/16.1/61.5, St. John's=-38.6/5.0/51.1, St. Louis=-27.3/13.9/61.6, Stockholm=-35.5/6.6/50.0, Surabaya=-15.5/27.1/76.1, Suva=-19.2/25.6/70.5, Suwałki=-40.9/7.2/50.1, Sydney=-28.0/17.6/69.6, Ségou=-23.0/28.0/73.0, Tabora=-24.6/23.0/71.2, Tabriz=-31.8/12.6/57.8, Taipei=-19.9/23.0/70.7, Tallinn=-36.7/6.4/51.4, Tamale=-16.7/27.9/75.9, Tamanrasset=-24.8/21.7/69.0, Tampa=-25.2/22.9/71.6, Tashkent=-31.2/14.8/65.3, Tauranga=-35.5/14.8/62.8, Tbilisi=-32.4/12.9/59.3, Tegucigalpa=-25.5/21.7/66.8, Tehran=-28.7/17.0/61.7, Tel Aviv=-24.3/20.0/64.7, Thessaloniki=-29.7/16.0/62.1, Thiès=-22.4/24.0/70.6, Tijuana=-25.8/17.8/64.8, Timbuktu=-15.3/28.0/80.0, Tirana=-34.3/15.2/61.9, Toamasina=-20.1/23.4/67.4, Tokyo=-33.6/15.4/60.6, Toliara=-24.5/24.1/74.4, Toluca=-31.6/12.4/58.0, Toronto=-37.2/9.4/51.9, Tripoli=-27.3/20.0/63.1, Tromsø=-40.8/2.9/48.1, Tucson=-25.6/20.9/62.6, Tunis=-24.6/18.4/60.0, Ulaanbaatar=-48.7/-0.4/46.3, Upington=-22.3/20.4/63.2, Vaduz=-37.0/10.1/55.8, Valencia=-25.9/18.3/68.5, Valletta=-25.2/18.8/66.4, Vancouver=-35.2/10.4/53.4, Veracruz=-22.5/25.4/67.7, Vienna=-33.4/10.4/55.0, Vientiane=-21.2/25.9/69.2, Villahermosa=-15.2/27.1/73.3, Vilnius=-40.0/6.0/52.7, Virginia Beach=-28.8/15.8/59.9, Vladivostok=-39.0/4.9/49.3, Warsaw=-34.0/8.5/53.5, Washington, D.C.=-30.2/14.6/59.8, Wau=-17.4/27.8/70.2, Wellington=-31.0/12.9/59.2, Whitehorse=-50.4/-0.1/46.7, Wichita=-29.7/13.9/60.1, Willemstad=-19.1/28.0/73.5, Winnipeg=-39.3/3.0/53.5, Wrocław=-41.4/9.6/53.7, Xi'an=-31.9/14.1/57.2, Yakutsk=-54.0/-8.8/33.5, Yangon=-19.6/27.5/76.4, Yaoundé=-23.8/23.8/69.9, Yellowknife=-55.5/-4.3/38.6, Yerevan=-30.0/12.4/61.0, Yinchuan=-36.8/9.0/53.4, Zagreb=-36.3/10.7/56.9, Zanzibar City=-20.4/26.0/71.5, Zürich=-36.0/9.3/56.3, Ürümqi=-40.5/7.4/54.5, İzmir=-29.5/17.9/61.2}"); + assert measurements.toString().equals( + "{Abha=-26.9/18.0/61.8, Abidjan=-23.3/26.0/71.5, Abéché=-19.4/29.4/72.3, Accra=-20.5/26.4/69.9, Addis Ababa=-29.5/16.0/62.3, Adelaide=-26.8/17.3/66.2, Aden=-14.8/29.1/76.1, Ahvaz=-20.7/25.4/70.3, Albuquerque=-33.5/14.0/56.9, Alexandra=-32.5/11.0/63.1, Alexandria=-26.7/20.0/62.5, Algiers=-30.7/18.2/63.5, Alice Springs=-27.6/21.0/66.7, Almaty=-35.9/10.0/53.7, Amsterdam=-34.9/10.2/55.0, Anadyr=-50.7/-6.9/42.5, Anchorage=-47.1/2.8/47.0, Andorra la Vella=-34.3/9.8/56.1, Ankara=-31.6/12.0/63.8, Antananarivo=-32.2/17.9/63.7, Antsiranana=-22.1/25.2/67.8, Arkhangelsk=-46.2/1.3/46.7, Ashgabat=-29.0/17.1/62.1, Asmara=-29.3/15.6/59.3, Assab=-14.5/30.5/76.5, Astana=-40.9/3.5/48.2, Athens=-29.2/19.2/61.6, Atlanta=-28.2/17.0/62.5, Auckland=-28.9/15.2/59.3, Austin=-23.4/20.7/63.5, Baghdad=-29.5/22.8/68.7, Baguio=-24.5/19.5/60.7, Baku=-27.7/15.1/59.7, Baltimore=-30.8/13.1/60.9, Bamako=-20.5/27.8/73.7, Bangkok=-18.6/28.6/75.1, Bangui=-21.1/26.0/71.6, Banjul=-18.0/26.0/70.5, Barcelona=-27.1/18.2/72.3, Bata=-30.7/25.1/69.2, Batumi=-30.6/14.0/59.2, Beijing=-32.4/12.9/55.0, Beirut=-24.7/20.9/67.3, Belgrade=-34.9/12.5/55.0, Belize City=-18.3/26.7/72.4, Benghazi=-27.4/19.9/65.6, Bergen=-35.2/7.7/51.9, Berlin=-38.5/10.3/59.7, Bilbao=-28.6/14.7/58.7, Birao=-23.7/26.5/73.5, Bishkek=-36.9/11.3/59.1, Bissau=-15.1/27.0/72.7, Blantyre=-25.4/22.2/75.5, Bloemfontein=-34.1/15.6/57.5, Boise=-34.6/11.4/60.5, Bordeaux=-29.9/14.2/57.0, Bosaso=-16.8/30.0/73.8, Boston=-32.7/10.9/56.2, Bouaké=-16.0/26.0/71.0, Bratislava=-32.3/10.5/55.6, Brazzaville=-19.3/25.0/70.8, Bridgetown=-16.3/27.0/70.4, Brisbane=-23.0/21.4/69.2, Brussels=-34.8/10.5/52.6, Bucharest=-30.0/10.8/56.4, Budapest=-36.4/11.3/54.6, Bujumbura=-24.3/23.8/69.5, Bulawayo=-23.5/18.9/60.7, Burnie=-32.2/13.0/57.4, Busan=-35.9/15.0/57.9, Cabo San Lucas=-18.4/23.9/67.8, Cairns=-18.9/25.0/69.6, Cairo=-28.0/21.4/64.9, Calgary=-41.2/4.4/51.4, Canberra=-28.6/13.1/56.3, Cape Town=-29.8/16.2/58.9, Changsha=-27.3/17.4/60.3, Charlotte=-29.6/16.1/60.9, Chiang Mai=-20.8/25.8/70.0, Chicago=-35.2/9.8/59.5, Chihuahua=-34.0/18.6/63.3, Chittagong=-19.8/25.9/74.8, Chișinău=-30.7/10.2/54.8, Chongqing=-24.6/18.6/66.6, Christchurch=-32.6/12.2/59.0, City of San Marino=-36.9/11.8/63.4, Colombo=-16.2/27.4/71.4, Columbus=-32.4/11.7/62.0, Conakry=-17.9/26.4/71.4, Copenhagen=-38.2/9.1/65.3, Cotonou=-19.8/27.2/73.2, Cracow=-33.4/9.3/58.5, Da Lat=-23.8/17.9/61.2, Da Nang=-19.2/25.8/70.1, Dakar=-20.7/24.0/68.6, Dallas=-25.3/18.9/63.5, Damascus=-28.4/17.0/63.7, Dampier=-18.6/26.4/70.2, Dar es Salaam=-17.7/25.8/69.2, Darwin=-14.5/27.6/74.8, Denpasar=-21.6/23.7/68.4, Denver=-32.1/10.4/59.0, Detroit=-36.8/10.0/56.6, Dhaka=-19.2/25.9/70.7, Dikson=-54.4/-11.1/37.8, Dili=-18.3/26.6/71.0, Djibouti=-18.2/29.9/76.6, Dodoma=-23.2/22.7/68.4, Dolisie=-20.9/24.0/66.2, Douala=-15.9/26.7/72.4, Dubai=-17.8/26.9/71.2, Dublin=-38.7/9.8/56.8, Dunedin=-35.2/11.1/55.4, Durban=-21.5/20.6/65.6, Dushanbe=-26.9/14.7/59.7, Edinburgh=-33.0/9.3/54.2, Edmonton=-38.9/4.2/48.5, El Paso=-24.3/18.1/63.7, Entebbe=-24.5/21.0/68.1, Erbil=-25.8/19.5/65.9, Erzurum=-38.8/5.1/49.0, Fairbanks=-47.4/-2.3/44.2, Fianarantsoa=-26.8/17.9/63.1, Flores, Petén=-21.1/26.4/73.4, Frankfurt=-35.6/10.6/56.2, Fresno=-23.9/17.9/67.4, Fukuoka=-28.0/17.0/62.0, Gaborone=-25.2/21.0/64.9, Gabès=-30.0/19.5/64.7, Gagnoa=-19.2/26.0/72.1, Gangtok=-33.3/15.2/63.1, Garissa=-19.4/29.3/83.4, Garoua=-16.4/28.3/80.1, George Town=-16.6/27.9/71.3, Ghanzi=-22.4/21.4/64.0, Gjoa Haven=-63.9/-14.4/30.8, Guadalajara=-22.7/20.9/69.1, Guangzhou=-34.0/22.4/69.4, Guatemala City=-26.7/20.4/63.4, Halifax=-35.5/7.5/50.5, Hamburg=-36.2/9.7/57.3, Hamilton=-28.9/13.8/58.9, Hanga Roa=-22.8/20.5/66.6, Hanoi=-20.2/23.6/70.3, Harare=-25.5/18.4/61.5, Harbin=-43.4/5.0/50.3, Hargeisa=-21.6/21.7/71.2, Hat Yai=-17.0/27.0/70.6, Havana=-28.3/25.2/74.0, Helsinki=-38.7/5.9/55.5, Heraklion=-25.4/18.9/64.9, Hiroshima=-28.7/16.3/60.7, Ho Chi Minh City=-21.3/27.4/69.2, Hobart=-34.4/12.7/60.7, Hong Kong=-23.9/23.3/66.6, Honiara=-17.9/26.5/72.1, Honolulu=-20.9/25.4/75.6, Houston=-28.3/20.8/64.4, Ifrane=-31.0/11.4/56.1, Indianapolis=-35.1/11.8/58.0, Iqaluit=-61.8/-9.3/38.7, Irkutsk=-49.6/1.0/46.7, Istanbul=-31.6/13.9/68.0, Jacksonville=-21.9/20.3/65.3, Jakarta=-18.2/26.7/74.0, Jayapura=-15.5/27.0/70.6, Jerusalem=-25.4/18.3/70.5, Johannesburg=-29.2/15.5/58.5, Jos=-22.4/22.8/66.3, Juba=-17.1/27.8/69.5, Kabul=-29.6/12.1/59.8, Kampala=-26.0/20.0/66.3, Kandi=-17.3/27.7/74.9, Kankan=-20.0/26.5/74.1, Kano=-20.0/26.4/69.8, Kansas City=-32.9/12.5/58.3, Karachi=-21.6/26.0/71.6, Karonga=-21.0/24.3/71.6, Kathmandu=-27.7/18.3/62.5, Khartoum=-20.3/29.9/78.0, Kingston=-17.6/27.4/69.9, Kinshasa=-22.6/25.3/70.1, Kolkata=-14.8/26.7/71.8, Kuala Lumpur=-17.6/27.3/73.1, Kumasi=-19.2/25.9/75.1, Kunming=-32.0/15.7/58.5, Kuopio=-45.8/3.4/46.5, Kuwait City=-19.2/25.7/71.2, Kyiv=-37.8/8.4/55.1, Kyoto=-27.2/15.8/64.9, La Ceiba=-17.8/26.2/72.7, La Paz=-23.7/23.7/66.4, Lagos=-16.6/26.8/74.6, Lahore=-19.8/24.3/70.3, Lake Havasu City=-24.8/23.7/68.3, Lake Tekapo=-36.3/8.7/54.1, Las Palmas de Gran Canaria=-29.4/21.2/66.7, Las Vegas=-24.9/20.3/64.8, Launceston=-32.0/13.1/57.2, Lhasa=-38.8/7.6/52.9, Libreville=-21.5/25.9/71.7, Lisbon=-34.9/17.5/65.6, Livingstone=-23.9/21.8/65.5, Ljubljana=-30.3/10.9/57.1, Lodwar=-14.8/29.3/73.1, Lomé=-17.5/26.9/70.7, London=-34.8/11.3/55.7, Los Angeles=-30.7/18.6/62.6, Louisville=-32.1/13.9/62.9, Luanda=-17.6/25.8/72.3, Lubumbashi=-26.0/20.8/66.9, Lusaka=-23.8/19.9/62.1, Luxembourg City=-33.0/9.3/56.0, Lviv=-36.1/7.8/51.7, Lyon=-36.7/12.5/56.8, Madrid=-30.4/15.0/59.1, Mahajanga=-17.2/26.3/67.9, Makassar=-14.9/26.7/73.1, Makurdi=-23.8/26.0/69.2, Malabo=-20.5/26.3/71.7, Malé=-21.6/28.0/75.4, Managua=-29.5/27.3/74.3, Manama=-20.3/26.5/72.8, Mandalay=-15.3/28.0/73.1, Mango=-14.7/28.1/74.5, Manila=-18.1/28.4/72.1, Maputo=-22.2/22.8/70.5, Marrakesh=-27.6/19.6/71.3, Marseille=-29.7/15.8/60.7, Maun=-21.5/22.4/65.6, Medan=-18.2/26.5/69.2, Mek'ele=-29.0/22.7/69.3, Melbourne=-29.6/15.1/64.2, Memphis=-27.3/17.2/61.6, Mexicali=-24.4/23.1/71.6, Mexico City=-27.1/17.5/63.1, Miami=-18.7/24.9/71.4, Milan=-32.9/13.0/59.2, Milwaukee=-33.9/8.9/55.1, Minneapolis=-35.5/7.8/50.9, Minsk=-35.2/6.8/53.5, Mogadishu=-18.6/27.1/73.9, Mombasa=-17.3/26.3/72.9, Monaco=-36.0/16.4/64.7, Moncton=-38.9/6.1/49.2, Monterrey=-20.0/22.3/66.4, Montreal=-41.5/6.8/53.1, Moscow=-40.5/5.8/50.6, Mumbai=-19.7/27.1/70.7, Murmansk=-47.6/0.6/49.6, Muscat=-16.9/28.0/78.6, Mzuzu=-25.7/17.7/60.6, N'Djamena=-15.5/28.3/71.7, Naha=-22.1/23.1/75.7, Nairobi=-29.7/17.8/60.1, Nakhon Ratchasima=-17.3/27.3/79.0, Napier=-33.7/14.6/58.0, Napoli=-25.7/15.9/61.1, Nashville=-33.2/15.4/59.1, Nassau=-20.4/24.6/67.9, Ndola=-23.4/20.3/64.5, New Delhi=-19.6/25.0/70.1, New Orleans=-24.3/20.7/64.5, New York City=-32.1/12.9/60.8, Ngaoundéré=-26.7/22.0/64.6, Niamey=-18.9/29.3/73.3, Nicosia=-27.2/19.7/64.8, Niigata=-29.8/13.9/60.0, Nouadhibou=-24.4/21.3/65.7, Nouakchott=-22.2/25.7/71.2, Novosibirsk=-40.9/1.7/45.7, Nuuk=-47.0/-1.4/48.1, Odesa=-41.9/10.7/53.1, Odienné=-25.7/26.0/70.0, Oklahoma City=-25.9/15.9/59.8, Omaha=-37.7/10.6/56.4, Oranjestad=-14.4/28.1/70.7, Oslo=-38.9/5.7/54.5, Ottawa=-39.2/6.6/48.7, Ouagadougou=-16.9/28.3/75.4, Ouahigouya=-15.7/28.6/75.0, Ouarzazate=-27.6/18.9/62.1, Oulu=-42.3/2.7/45.1, Palembang=-19.7/27.3/71.1, Palermo=-27.2/18.5/63.0, Palm Springs=-26.7/24.5/73.4, Palmerston North=-36.3/13.2/56.0, Panama City=-19.2/28.0/76.6, Parakou=-16.4/26.8/69.9, Paris=-33.4/12.3/57.6, Perth=-28.3/18.7/67.7, Petropavlovsk-Kamchatsky=-41.7/1.9/49.3, Philadelphia=-32.9/13.2/59.4, Phnom Penh=-15.2/28.3/73.5, Phoenix=-18.7/23.9/69.1, Pittsburgh=-38.1/10.8/57.1, Podgorica=-32.2/15.3/58.9, Pointe-Noire=-20.8/26.1/70.7, Pontianak=-18.5/27.7/75.5, Port Moresby=-16.6/26.9/69.7, Port Sudan=-12.9/28.4/75.4, Port Vila=-20.4/24.3/71.3, Port-Gentil=-16.6/26.0/74.4, Portland (OR)=-31.7/12.4/60.2, Porto=-29.1/15.7/57.6, Prague=-41.1/8.4/54.7, Praia=-21.5/24.4/70.7, Pretoria=-26.5/18.2/64.6, Pyongyang=-32.6/10.8/55.7, Rabat=-28.3/17.2/61.1, Rangpur=-19.4/24.4/67.5, Reggane=-19.0/28.3/70.8, Reykjavík=-41.3/4.3/47.3, Riga=-41.8/6.2/54.3, Riyadh=-26.1/26.1/69.6, Rome=-27.6/15.2/58.4, Roseau=-23.1/26.2/67.8, Rostov-on-Don=-34.0/9.9/58.3, Sacramento=-31.3/16.3/59.9, Saint Petersburg=-37.5/5.8/48.8, Saint-Pierre=-39.5/5.7/49.8, Salt Lake City=-35.6/11.6/55.5, San Antonio=-28.7/20.8/66.1, San Diego=-26.0/17.8/67.9, San Francisco=-28.4/14.6/64.1, San Jose=-25.6/16.4/58.4, San José=-20.7/22.6/67.3, San Juan=-15.3/27.2/72.2, San Salvador=-20.9/23.1/65.7, Sana'a=-28.1/20.0/65.4, Santo Domingo=-19.2/25.9/70.6, Sapporo=-36.1/8.9/54.1, Sarajevo=-42.5/10.1/62.6, Saskatoon=-42.5/3.3/49.9, Seattle=-34.8/11.3/56.1, Seoul=-30.7/12.5/58.2, Seville=-22.1/19.1/64.5, Shanghai=-25.4/16.7/68.4, Singapore=-19.2/27.0/74.2, Skopje=-33.3/12.4/57.6, Sochi=-29.8/14.2/62.2, Sofia=-35.1/10.6/53.6, Sokoto=-19.1/28.0/75.1, Split=-26.8/16.1/61.5, St. John's=-38.6/5.0/51.1, St. Louis=-27.3/13.9/61.6, Stockholm=-35.5/6.6/50.0, Surabaya=-15.5/27.1/76.1, Suva=-19.2/25.6/70.5, Suwałki=-40.9/7.2/50.1, Sydney=-28.0/17.6/69.6, Ségou=-23.0/28.0/73.0, Tabora=-24.6/23.0/71.2, Tabriz=-31.8/12.6/57.8, Taipei=-19.9/23.0/70.7, Tallinn=-36.7/6.4/51.4, Tamale=-16.7/27.9/75.9, Tamanrasset=-24.8/21.7/69.0, Tampa=-25.2/22.9/71.6, Tashkent=-31.2/14.8/65.3, Tauranga=-35.5/14.8/62.8, Tbilisi=-32.4/12.9/59.3, Tegucigalpa=-25.5/21.7/66.8, Tehran=-28.7/17.0/61.7, Tel Aviv=-24.3/20.0/64.7, Thessaloniki=-29.7/16.0/62.1, Thiès=-22.4/24.0/70.6, Tijuana=-25.8/17.8/64.8, Timbuktu=-15.3/28.0/80.0, Tirana=-34.3/15.2/61.9, Toamasina=-20.1/23.4/67.4, Tokyo=-33.6/15.4/60.6, Toliara=-24.5/24.1/74.4, Toluca=-31.6/12.4/58.0, Toronto=-37.2/9.4/51.9, Tripoli=-27.3/20.0/63.1, Tromsø=-40.8/2.9/48.1, Tucson=-25.6/20.9/62.6, Tunis=-24.6/18.4/60.0, Ulaanbaatar=-48.7/-0.4/46.3, Upington=-22.3/20.4/63.2, Vaduz=-37.0/10.1/55.8, Valencia=-25.9/18.3/68.5, Valletta=-25.2/18.8/66.4, Vancouver=-35.2/10.4/53.4, Veracruz=-22.5/25.4/67.7, Vienna=-33.4/10.4/55.0, Vientiane=-21.2/25.9/69.2, Villahermosa=-15.2/27.1/73.3, Vilnius=-40.0/6.0/52.7, Virginia Beach=-28.8/15.8/59.9, Vladivostok=-39.0/4.9/49.3, Warsaw=-34.0/8.5/53.5, Washington, D.C.=-30.2/14.6/59.8, Wau=-17.4/27.8/70.2, Wellington=-31.0/12.9/59.2, Whitehorse=-50.4/-0.1/46.7, Wichita=-29.7/13.9/60.1, Willemstad=-19.1/28.0/73.5, Winnipeg=-39.3/3.0/53.5, Wrocław=-41.4/9.6/53.7, Xi'an=-31.9/14.1/57.2, Yakutsk=-54.0/-8.8/33.5, Yangon=-19.6/27.5/76.4, Yaoundé=-23.8/23.8/69.9, Yellowknife=-55.5/-4.3/38.6, Yerevan=-30.0/12.4/61.0, Yinchuan=-36.8/9.0/53.4, Zagreb=-36.3/10.7/56.9, Zanzibar City=-20.4/26.0/71.5, Zürich=-36.0/9.3/56.3, Ürümqi=-40.5/7.4/54.5, İzmir=-29.5/17.9/61.2}"); } private static String[] fastSplit(String str) { From d84a073c4029c96846ca351a12f7417359fa0190 Mon Sep 17 00:00:00 2001 From: twobiers <22715034+twobiers@users.noreply.github.com> Date: Mon, 1 Jan 2024 19:02:38 +0100 Subject: [PATCH 12/18] remove compact strings --- calculate_average_twobiers.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/calculate_average_twobiers.sh b/calculate_average_twobiers.sh index f7ecd84c9..ed4f0c64e 100755 --- a/calculate_average_twobiers.sh +++ b/calculate_average_twobiers.sh @@ -15,5 +15,5 @@ # limitations under the License. # -JAVA_OPTS="-XX:+UseStringDeduplication -XX:+CompactStrings -XX:+UseTransparentHugePages -da" +JAVA_OPTS="-XX:+UseStringDeduplication -XX:+UseTransparentHugePages -da" java $JAVA_OPTS --class-path target/average-1.0.0-SNAPSHOT.jar dev.morling.onebrc.CalculateAverage_twobiers From 724f8cc0fbafe5ce9a63d28707fccf6536a3b5dd Mon Sep 17 00:00:00 2001 From: twobiers <22715034+twobiers@users.noreply.github.com> Date: Mon, 1 Jan 2024 20:11:53 +0100 Subject: [PATCH 13/18] replace sumWithCompensation with naive sum implementation --- .../onebrc/CalculateAverage_twobiers.java | 25 ++++++------------- 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java b/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java index 26abcf44a..35c0aaf2e 100644 --- a/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java +++ b/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java @@ -39,10 +39,9 @@ public class CalculateAverage_twobiers { private static class FastAveragingCollector implements Collector { @Override public Supplier supplier() { - // 0: summand 1 - // 1: summand 2 + // 0: parsed value + // 1: current sum // 2: count - // 3: parsed value // 4: current max // 5: current min return () -> new double[6]; @@ -52,9 +51,11 @@ public Supplier supplier() { public BiConsumer accumulator() { return (a, t) -> { double val = fastParseDouble(t[1]); - sumWithCompensation(a, val); + + a[0] = val; + a[1] += val; a[2]++; - a[3] += val; + if (val > a[4]) { a[4] = val; } @@ -67,11 +68,8 @@ public BiConsumer accumulator() { @Override public BinaryOperator combiner() { return (a, b) -> { - sumWithCompensation(a, b[0]); - // Subtract compensation bits - sumWithCompensation(a, -b[1]); a[2] += b[2]; - a[3] += b[3]; + a[1] += b[1]; if (b[4] > a[4]) { a[4] = b[4]; } @@ -212,13 +210,4 @@ private static double asDouble(long value, int exp, boolean negative, int decima return negative ? -d : d; } - private static double[] sumWithCompensation(double[] intermediateSum, double value) { - double tmp = value - intermediateSum[1]; - double sum = intermediateSum[0]; - double velvel = sum + tmp; // Little wolf of rounding error - intermediateSum[1] = (velvel - sum) - tmp; - intermediateSum[0] = velvel; - return intermediateSum; - } - } From 83b7367487890f9eb3a3010541ecd6547672c2a3 Mon Sep 17 00:00:00 2001 From: twobiers <22715034+twobiers@users.noreply.github.com> Date: Tue, 2 Jan 2024 17:42:28 +0100 Subject: [PATCH 14/18] use UseShenandoahGC --- calculate_average_twobiers.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/calculate_average_twobiers.sh b/calculate_average_twobiers.sh index ed4f0c64e..3d4b97d6b 100755 --- a/calculate_average_twobiers.sh +++ b/calculate_average_twobiers.sh @@ -15,5 +15,5 @@ # limitations under the License. # -JAVA_OPTS="-XX:+UseStringDeduplication -XX:+UseTransparentHugePages -da" +JAVA_OPTS="-XX:+UseShenandoahGC -XX:+UseStringDeduplication -XX:+UseTransparentHugePages -da" java $JAVA_OPTS --class-path target/average-1.0.0-SNAPSHOT.jar dev.morling.onebrc.CalculateAverage_twobiers From b04f3f9a7207558e41292cc42b5fb0891db0a08a Mon Sep 17 00:00:00 2001 From: twobiers <22715034+twobiers@users.noreply.github.com> Date: Tue, 2 Jan 2024 21:05:17 +0100 Subject: [PATCH 15/18] integrate mmap --- .../onebrc/CalculateAverage_twobiers.java | 145 ++++++++++++++---- 1 file changed, 113 insertions(+), 32 deletions(-) diff --git a/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java b/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java index 35c0aaf2e..fd12becdf 100644 --- a/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java +++ b/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java @@ -18,17 +18,25 @@ import static java.util.stream.Collectors.groupingBy; import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.Arrays; +import java.io.RandomAccessFile; +import java.nio.ByteBuffer; +import java.nio.MappedByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.channels.FileChannel.MapMode; +import java.util.ArrayList; import java.util.Collections; +import java.util.Iterator; +import java.util.List; import java.util.Set; +import java.util.Spliterator; +import java.util.Spliterators; import java.util.TreeMap; import java.util.function.BiConsumer; import java.util.function.BinaryOperator; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collector; +import java.util.stream.StreamSupport; public class CalculateAverage_twobiers { @@ -36,7 +44,7 @@ public class CalculateAverage_twobiers { private static final FastAveragingCollector FAST_AVERAGING_COLLECTOR = new FastAveragingCollector(); // private static final VectorSpecies SPECIES = IntVector.SPECIES_256; - private static class FastAveragingCollector implements Collector { + private static class FastAveragingCollector implements Collector { @Override public Supplier supplier() { // 0: parsed value @@ -48,9 +56,9 @@ public Supplier supplier() { } @Override - public BiConsumer accumulator() { + public BiConsumer accumulator() { return (a, t) -> { - double val = fastParseDouble(t[1]); + double val = t.value(); a[0] = val; a[1] += val; @@ -96,47 +104,121 @@ public Set characteristics() { } } + private static class FileChannelIterator implements Iterator { + private static final long CHUNK_SIZE = (long) Math.pow(2, 19); + + private final FileChannel fileChannel; + private final long size; + private long bytesRead = 0; + + public FileChannelIterator(FileChannel fileChannel) { + this.fileChannel = fileChannel; + try { + this.size = fileChannel.size(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public boolean hasNext() { + return bytesRead < size; + } + + @Override + public ByteBuffer next() { + try { + MappedByteBuffer mappedByteBuffer = fileChannel.map(MapMode.READ_ONLY, bytesRead, Math.min(CHUNK_SIZE, size - bytesRead)); + + int realEnd = mappedByteBuffer.limit() - 1; + while (mappedByteBuffer.get(realEnd) != '\n') { + realEnd--; + } + mappedByteBuffer.limit(++realEnd); + bytesRead += realEnd; + + return mappedByteBuffer; + } + catch (IOException e) { + throw new RuntimeException(e); + } + } + } + + private record Measurement(String station, double value) {} + public static void main(String[] args) throws IOException { - TreeMap measurements = Files.lines(Paths.get(FILE)) - .parallel() - .map(l -> fastSplit(l)) + try( + var file = new RandomAccessFile(FILE, "r"); + var channel = file.getChannel(); + ) { + TreeMap measurements = StreamSupport.stream( + Spliterators.spliteratorUnknownSize(new FileChannelIterator(channel), + Spliterator.IMMUTABLE), true) + .flatMap(a -> parseMeasurements(a).stream()) .collect( - groupingBy( - m -> m[0], - TreeMap::new, - FAST_AVERAGING_COLLECTOR)); + groupingBy( + Measurement::station, + TreeMap::new, + FAST_AVERAGING_COLLECTOR)); - System.out.println(measurements); + System.out.println(measurements); - // Simple test for my generated file - assert measurements.toString().equals( - "{Abha=-26.9/18.0/61.8, Abidjan=-23.3/26.0/71.5, Abéché=-19.4/29.4/72.3, Accra=-20.5/26.4/69.9, Addis Ababa=-29.5/16.0/62.3, Adelaide=-26.8/17.3/66.2, Aden=-14.8/29.1/76.1, Ahvaz=-20.7/25.4/70.3, Albuquerque=-33.5/14.0/56.9, Alexandra=-32.5/11.0/63.1, Alexandria=-26.7/20.0/62.5, Algiers=-30.7/18.2/63.5, Alice Springs=-27.6/21.0/66.7, Almaty=-35.9/10.0/53.7, Amsterdam=-34.9/10.2/55.0, Anadyr=-50.7/-6.9/42.5, Anchorage=-47.1/2.8/47.0, Andorra la Vella=-34.3/9.8/56.1, Ankara=-31.6/12.0/63.8, Antananarivo=-32.2/17.9/63.7, Antsiranana=-22.1/25.2/67.8, Arkhangelsk=-46.2/1.3/46.7, Ashgabat=-29.0/17.1/62.1, Asmara=-29.3/15.6/59.3, Assab=-14.5/30.5/76.5, Astana=-40.9/3.5/48.2, Athens=-29.2/19.2/61.6, Atlanta=-28.2/17.0/62.5, Auckland=-28.9/15.2/59.3, Austin=-23.4/20.7/63.5, Baghdad=-29.5/22.8/68.7, Baguio=-24.5/19.5/60.7, Baku=-27.7/15.1/59.7, Baltimore=-30.8/13.1/60.9, Bamako=-20.5/27.8/73.7, Bangkok=-18.6/28.6/75.1, Bangui=-21.1/26.0/71.6, Banjul=-18.0/26.0/70.5, Barcelona=-27.1/18.2/72.3, Bata=-30.7/25.1/69.2, Batumi=-30.6/14.0/59.2, Beijing=-32.4/12.9/55.0, Beirut=-24.7/20.9/67.3, Belgrade=-34.9/12.5/55.0, Belize City=-18.3/26.7/72.4, Benghazi=-27.4/19.9/65.6, Bergen=-35.2/7.7/51.9, Berlin=-38.5/10.3/59.7, Bilbao=-28.6/14.7/58.7, Birao=-23.7/26.5/73.5, Bishkek=-36.9/11.3/59.1, Bissau=-15.1/27.0/72.7, Blantyre=-25.4/22.2/75.5, Bloemfontein=-34.1/15.6/57.5, Boise=-34.6/11.4/60.5, Bordeaux=-29.9/14.2/57.0, Bosaso=-16.8/30.0/73.8, Boston=-32.7/10.9/56.2, Bouaké=-16.0/26.0/71.0, Bratislava=-32.3/10.5/55.6, Brazzaville=-19.3/25.0/70.8, Bridgetown=-16.3/27.0/70.4, Brisbane=-23.0/21.4/69.2, Brussels=-34.8/10.5/52.6, Bucharest=-30.0/10.8/56.4, Budapest=-36.4/11.3/54.6, Bujumbura=-24.3/23.8/69.5, Bulawayo=-23.5/18.9/60.7, Burnie=-32.2/13.0/57.4, Busan=-35.9/15.0/57.9, Cabo San Lucas=-18.4/23.9/67.8, Cairns=-18.9/25.0/69.6, Cairo=-28.0/21.4/64.9, Calgary=-41.2/4.4/51.4, Canberra=-28.6/13.1/56.3, Cape Town=-29.8/16.2/58.9, Changsha=-27.3/17.4/60.3, Charlotte=-29.6/16.1/60.9, Chiang Mai=-20.8/25.8/70.0, Chicago=-35.2/9.8/59.5, Chihuahua=-34.0/18.6/63.3, Chittagong=-19.8/25.9/74.8, Chișinău=-30.7/10.2/54.8, Chongqing=-24.6/18.6/66.6, Christchurch=-32.6/12.2/59.0, City of San Marino=-36.9/11.8/63.4, Colombo=-16.2/27.4/71.4, Columbus=-32.4/11.7/62.0, Conakry=-17.9/26.4/71.4, Copenhagen=-38.2/9.1/65.3, Cotonou=-19.8/27.2/73.2, Cracow=-33.4/9.3/58.5, Da Lat=-23.8/17.9/61.2, Da Nang=-19.2/25.8/70.1, Dakar=-20.7/24.0/68.6, Dallas=-25.3/18.9/63.5, Damascus=-28.4/17.0/63.7, Dampier=-18.6/26.4/70.2, Dar es Salaam=-17.7/25.8/69.2, Darwin=-14.5/27.6/74.8, Denpasar=-21.6/23.7/68.4, Denver=-32.1/10.4/59.0, Detroit=-36.8/10.0/56.6, Dhaka=-19.2/25.9/70.7, Dikson=-54.4/-11.1/37.8, Dili=-18.3/26.6/71.0, Djibouti=-18.2/29.9/76.6, Dodoma=-23.2/22.7/68.4, Dolisie=-20.9/24.0/66.2, Douala=-15.9/26.7/72.4, Dubai=-17.8/26.9/71.2, Dublin=-38.7/9.8/56.8, Dunedin=-35.2/11.1/55.4, Durban=-21.5/20.6/65.6, Dushanbe=-26.9/14.7/59.7, Edinburgh=-33.0/9.3/54.2, Edmonton=-38.9/4.2/48.5, El Paso=-24.3/18.1/63.7, Entebbe=-24.5/21.0/68.1, Erbil=-25.8/19.5/65.9, Erzurum=-38.8/5.1/49.0, Fairbanks=-47.4/-2.3/44.2, Fianarantsoa=-26.8/17.9/63.1, Flores, Petén=-21.1/26.4/73.4, Frankfurt=-35.6/10.6/56.2, Fresno=-23.9/17.9/67.4, Fukuoka=-28.0/17.0/62.0, Gaborone=-25.2/21.0/64.9, Gabès=-30.0/19.5/64.7, Gagnoa=-19.2/26.0/72.1, Gangtok=-33.3/15.2/63.1, Garissa=-19.4/29.3/83.4, Garoua=-16.4/28.3/80.1, George Town=-16.6/27.9/71.3, Ghanzi=-22.4/21.4/64.0, Gjoa Haven=-63.9/-14.4/30.8, Guadalajara=-22.7/20.9/69.1, Guangzhou=-34.0/22.4/69.4, Guatemala City=-26.7/20.4/63.4, Halifax=-35.5/7.5/50.5, Hamburg=-36.2/9.7/57.3, Hamilton=-28.9/13.8/58.9, Hanga Roa=-22.8/20.5/66.6, Hanoi=-20.2/23.6/70.3, Harare=-25.5/18.4/61.5, Harbin=-43.4/5.0/50.3, Hargeisa=-21.6/21.7/71.2, Hat Yai=-17.0/27.0/70.6, Havana=-28.3/25.2/74.0, Helsinki=-38.7/5.9/55.5, Heraklion=-25.4/18.9/64.9, Hiroshima=-28.7/16.3/60.7, Ho Chi Minh City=-21.3/27.4/69.2, Hobart=-34.4/12.7/60.7, Hong Kong=-23.9/23.3/66.6, Honiara=-17.9/26.5/72.1, Honolulu=-20.9/25.4/75.6, Houston=-28.3/20.8/64.4, Ifrane=-31.0/11.4/56.1, Indianapolis=-35.1/11.8/58.0, Iqaluit=-61.8/-9.3/38.7, Irkutsk=-49.6/1.0/46.7, Istanbul=-31.6/13.9/68.0, Jacksonville=-21.9/20.3/65.3, Jakarta=-18.2/26.7/74.0, Jayapura=-15.5/27.0/70.6, Jerusalem=-25.4/18.3/70.5, Johannesburg=-29.2/15.5/58.5, Jos=-22.4/22.8/66.3, Juba=-17.1/27.8/69.5, Kabul=-29.6/12.1/59.8, Kampala=-26.0/20.0/66.3, Kandi=-17.3/27.7/74.9, Kankan=-20.0/26.5/74.1, Kano=-20.0/26.4/69.8, Kansas City=-32.9/12.5/58.3, Karachi=-21.6/26.0/71.6, Karonga=-21.0/24.3/71.6, Kathmandu=-27.7/18.3/62.5, Khartoum=-20.3/29.9/78.0, Kingston=-17.6/27.4/69.9, Kinshasa=-22.6/25.3/70.1, Kolkata=-14.8/26.7/71.8, Kuala Lumpur=-17.6/27.3/73.1, Kumasi=-19.2/25.9/75.1, Kunming=-32.0/15.7/58.5, Kuopio=-45.8/3.4/46.5, Kuwait City=-19.2/25.7/71.2, Kyiv=-37.8/8.4/55.1, Kyoto=-27.2/15.8/64.9, La Ceiba=-17.8/26.2/72.7, La Paz=-23.7/23.7/66.4, Lagos=-16.6/26.8/74.6, Lahore=-19.8/24.3/70.3, Lake Havasu City=-24.8/23.7/68.3, Lake Tekapo=-36.3/8.7/54.1, Las Palmas de Gran Canaria=-29.4/21.2/66.7, Las Vegas=-24.9/20.3/64.8, Launceston=-32.0/13.1/57.2, Lhasa=-38.8/7.6/52.9, Libreville=-21.5/25.9/71.7, Lisbon=-34.9/17.5/65.6, Livingstone=-23.9/21.8/65.5, Ljubljana=-30.3/10.9/57.1, Lodwar=-14.8/29.3/73.1, Lomé=-17.5/26.9/70.7, London=-34.8/11.3/55.7, Los Angeles=-30.7/18.6/62.6, Louisville=-32.1/13.9/62.9, Luanda=-17.6/25.8/72.3, Lubumbashi=-26.0/20.8/66.9, Lusaka=-23.8/19.9/62.1, Luxembourg City=-33.0/9.3/56.0, Lviv=-36.1/7.8/51.7, Lyon=-36.7/12.5/56.8, Madrid=-30.4/15.0/59.1, Mahajanga=-17.2/26.3/67.9, Makassar=-14.9/26.7/73.1, Makurdi=-23.8/26.0/69.2, Malabo=-20.5/26.3/71.7, Malé=-21.6/28.0/75.4, Managua=-29.5/27.3/74.3, Manama=-20.3/26.5/72.8, Mandalay=-15.3/28.0/73.1, Mango=-14.7/28.1/74.5, Manila=-18.1/28.4/72.1, Maputo=-22.2/22.8/70.5, Marrakesh=-27.6/19.6/71.3, Marseille=-29.7/15.8/60.7, Maun=-21.5/22.4/65.6, Medan=-18.2/26.5/69.2, Mek'ele=-29.0/22.7/69.3, Melbourne=-29.6/15.1/64.2, Memphis=-27.3/17.2/61.6, Mexicali=-24.4/23.1/71.6, Mexico City=-27.1/17.5/63.1, Miami=-18.7/24.9/71.4, Milan=-32.9/13.0/59.2, Milwaukee=-33.9/8.9/55.1, Minneapolis=-35.5/7.8/50.9, Minsk=-35.2/6.8/53.5, Mogadishu=-18.6/27.1/73.9, Mombasa=-17.3/26.3/72.9, Monaco=-36.0/16.4/64.7, Moncton=-38.9/6.1/49.2, Monterrey=-20.0/22.3/66.4, Montreal=-41.5/6.8/53.1, Moscow=-40.5/5.8/50.6, Mumbai=-19.7/27.1/70.7, Murmansk=-47.6/0.6/49.6, Muscat=-16.9/28.0/78.6, Mzuzu=-25.7/17.7/60.6, N'Djamena=-15.5/28.3/71.7, Naha=-22.1/23.1/75.7, Nairobi=-29.7/17.8/60.1, Nakhon Ratchasima=-17.3/27.3/79.0, Napier=-33.7/14.6/58.0, Napoli=-25.7/15.9/61.1, Nashville=-33.2/15.4/59.1, Nassau=-20.4/24.6/67.9, Ndola=-23.4/20.3/64.5, New Delhi=-19.6/25.0/70.1, New Orleans=-24.3/20.7/64.5, New York City=-32.1/12.9/60.8, Ngaoundéré=-26.7/22.0/64.6, Niamey=-18.9/29.3/73.3, Nicosia=-27.2/19.7/64.8, Niigata=-29.8/13.9/60.0, Nouadhibou=-24.4/21.3/65.7, Nouakchott=-22.2/25.7/71.2, Novosibirsk=-40.9/1.7/45.7, Nuuk=-47.0/-1.4/48.1, Odesa=-41.9/10.7/53.1, Odienné=-25.7/26.0/70.0, Oklahoma City=-25.9/15.9/59.8, Omaha=-37.7/10.6/56.4, Oranjestad=-14.4/28.1/70.7, Oslo=-38.9/5.7/54.5, Ottawa=-39.2/6.6/48.7, Ouagadougou=-16.9/28.3/75.4, Ouahigouya=-15.7/28.6/75.0, Ouarzazate=-27.6/18.9/62.1, Oulu=-42.3/2.7/45.1, Palembang=-19.7/27.3/71.1, Palermo=-27.2/18.5/63.0, Palm Springs=-26.7/24.5/73.4, Palmerston North=-36.3/13.2/56.0, Panama City=-19.2/28.0/76.6, Parakou=-16.4/26.8/69.9, Paris=-33.4/12.3/57.6, Perth=-28.3/18.7/67.7, Petropavlovsk-Kamchatsky=-41.7/1.9/49.3, Philadelphia=-32.9/13.2/59.4, Phnom Penh=-15.2/28.3/73.5, Phoenix=-18.7/23.9/69.1, Pittsburgh=-38.1/10.8/57.1, Podgorica=-32.2/15.3/58.9, Pointe-Noire=-20.8/26.1/70.7, Pontianak=-18.5/27.7/75.5, Port Moresby=-16.6/26.9/69.7, Port Sudan=-12.9/28.4/75.4, Port Vila=-20.4/24.3/71.3, Port-Gentil=-16.6/26.0/74.4, Portland (OR)=-31.7/12.4/60.2, Porto=-29.1/15.7/57.6, Prague=-41.1/8.4/54.7, Praia=-21.5/24.4/70.7, Pretoria=-26.5/18.2/64.6, Pyongyang=-32.6/10.8/55.7, Rabat=-28.3/17.2/61.1, Rangpur=-19.4/24.4/67.5, Reggane=-19.0/28.3/70.8, Reykjavík=-41.3/4.3/47.3, Riga=-41.8/6.2/54.3, Riyadh=-26.1/26.1/69.6, Rome=-27.6/15.2/58.4, Roseau=-23.1/26.2/67.8, Rostov-on-Don=-34.0/9.9/58.3, Sacramento=-31.3/16.3/59.9, Saint Petersburg=-37.5/5.8/48.8, Saint-Pierre=-39.5/5.7/49.8, Salt Lake City=-35.6/11.6/55.5, San Antonio=-28.7/20.8/66.1, San Diego=-26.0/17.8/67.9, San Francisco=-28.4/14.6/64.1, San Jose=-25.6/16.4/58.4, San José=-20.7/22.6/67.3, San Juan=-15.3/27.2/72.2, San Salvador=-20.9/23.1/65.7, Sana'a=-28.1/20.0/65.4, Santo Domingo=-19.2/25.9/70.6, Sapporo=-36.1/8.9/54.1, Sarajevo=-42.5/10.1/62.6, Saskatoon=-42.5/3.3/49.9, Seattle=-34.8/11.3/56.1, Seoul=-30.7/12.5/58.2, Seville=-22.1/19.1/64.5, Shanghai=-25.4/16.7/68.4, Singapore=-19.2/27.0/74.2, Skopje=-33.3/12.4/57.6, Sochi=-29.8/14.2/62.2, Sofia=-35.1/10.6/53.6, Sokoto=-19.1/28.0/75.1, Split=-26.8/16.1/61.5, St. John's=-38.6/5.0/51.1, St. Louis=-27.3/13.9/61.6, Stockholm=-35.5/6.6/50.0, Surabaya=-15.5/27.1/76.1, Suva=-19.2/25.6/70.5, Suwałki=-40.9/7.2/50.1, Sydney=-28.0/17.6/69.6, Ségou=-23.0/28.0/73.0, Tabora=-24.6/23.0/71.2, Tabriz=-31.8/12.6/57.8, Taipei=-19.9/23.0/70.7, Tallinn=-36.7/6.4/51.4, Tamale=-16.7/27.9/75.9, Tamanrasset=-24.8/21.7/69.0, Tampa=-25.2/22.9/71.6, Tashkent=-31.2/14.8/65.3, Tauranga=-35.5/14.8/62.8, Tbilisi=-32.4/12.9/59.3, Tegucigalpa=-25.5/21.7/66.8, Tehran=-28.7/17.0/61.7, Tel Aviv=-24.3/20.0/64.7, Thessaloniki=-29.7/16.0/62.1, Thiès=-22.4/24.0/70.6, Tijuana=-25.8/17.8/64.8, Timbuktu=-15.3/28.0/80.0, Tirana=-34.3/15.2/61.9, Toamasina=-20.1/23.4/67.4, Tokyo=-33.6/15.4/60.6, Toliara=-24.5/24.1/74.4, Toluca=-31.6/12.4/58.0, Toronto=-37.2/9.4/51.9, Tripoli=-27.3/20.0/63.1, Tromsø=-40.8/2.9/48.1, Tucson=-25.6/20.9/62.6, Tunis=-24.6/18.4/60.0, Ulaanbaatar=-48.7/-0.4/46.3, Upington=-22.3/20.4/63.2, Vaduz=-37.0/10.1/55.8, Valencia=-25.9/18.3/68.5, Valletta=-25.2/18.8/66.4, Vancouver=-35.2/10.4/53.4, Veracruz=-22.5/25.4/67.7, Vienna=-33.4/10.4/55.0, Vientiane=-21.2/25.9/69.2, Villahermosa=-15.2/27.1/73.3, Vilnius=-40.0/6.0/52.7, Virginia Beach=-28.8/15.8/59.9, Vladivostok=-39.0/4.9/49.3, Warsaw=-34.0/8.5/53.5, Washington, D.C.=-30.2/14.6/59.8, Wau=-17.4/27.8/70.2, Wellington=-31.0/12.9/59.2, Whitehorse=-50.4/-0.1/46.7, Wichita=-29.7/13.9/60.1, Willemstad=-19.1/28.0/73.5, Winnipeg=-39.3/3.0/53.5, Wrocław=-41.4/9.6/53.7, Xi'an=-31.9/14.1/57.2, Yakutsk=-54.0/-8.8/33.5, Yangon=-19.6/27.5/76.4, Yaoundé=-23.8/23.8/69.9, Yellowknife=-55.5/-4.3/38.6, Yerevan=-30.0/12.4/61.0, Yinchuan=-36.8/9.0/53.4, Zagreb=-36.3/10.7/56.9, Zanzibar City=-20.4/26.0/71.5, Zürich=-36.0/9.3/56.3, Ürümqi=-40.5/7.4/54.5, İzmir=-29.5/17.9/61.2}"); + // Simple test for my generated file + assert measurements.toString().equals( + "{Abha=-30.1/18.0/72.2, Abidjan=-23.4/26.0/79.9, Abéché=-17.3/29.4/80.5, Accra=-24.3/26.4/77.9, Addis Ababa=-33.6/16.0/65.9, Adelaide=-33.7/17.3/71.1, Aden=-21.2/29.1/81.2, Ahvaz=-30.2/25.4/80.2, Albuquerque=-39.1/14.0/60.9, Alexandra=-36.6/11.0/62.9, Alexandria=-30.4/20.0/69.8, Algiers=-33.1/18.2/68.4, Alice Springs=-27.2/21.0/72.1, Almaty=-40.5/10.0/58.5, Amsterdam=-38.9/10.2/58.9, Anadyr=-58.2/-6.9/39.9, Anchorage=-45.3/2.8/54.3, Andorra la Vella=-42.9/9.8/60.6, Ankara=-36.7/12.0/63.7, Antananarivo=-30.9/17.9/70.8, Antsiranana=-23.0/25.2/75.4, Arkhangelsk=-48.2/1.3/51.4, Ashgabat=-30.4/17.1/64.9, Asmara=-32.6/15.6/65.4, Assab=-21.2/30.5/78.7, Astana=-45.5/3.5/49.3, Athens=-28.5/19.2/68.0, Atlanta=-33.3/17.0/69.7, Auckland=-33.6/15.2/65.0, Austin=-32.1/20.7/68.5, Baghdad=-29.6/22.8/71.6, Baguio=-29.9/19.5/68.7, Baku=-32.1/15.1/66.8, Baltimore=-36.4/13.1/62.8, Bamako=-27.0/27.8/82.0, Bangkok=-20.5/28.6/79.0, Bangui=-24.2/26.0/73.8, Banjul=-27.0/26.0/75.4, Barcelona=-36.1/18.2/74.0, Bata=-25.9/25.1/73.7, Batumi=-36.8/14.0/65.7, Beijing=-34.2/12.9/65.9, Beirut=-28.9/20.9/68.5, Belgrade=-35.7/12.5/65.5, Belize City=-24.8/26.7/75.3, Benghazi=-28.6/19.9/68.9, Bergen=-48.8/7.7/58.5, Berlin=-48.1/10.3/62.5, Bilbao=-34.5/14.7/65.2, Birao=-22.7/26.5/77.9, Bishkek=-37.2/11.3/62.1, Bissau=-24.1/27.0/82.6, Blantyre=-29.2/22.2/68.9, Bloemfontein=-32.1/15.6/66.1, Boise=-36.6/11.4/62.2, Bordeaux=-34.2/14.2/63.0, Bosaso=-20.8/30.0/77.2, Boston=-39.8/10.9/58.4, Bouaké=-24.8/26.0/76.8, Bratislava=-40.5/10.5/62.6, Brazzaville=-29.3/25.0/74.6, Bridgetown=-25.0/27.0/78.4, Brisbane=-27.2/21.4/69.7, Brussels=-37.0/10.5/56.6, Bucharest=-48.7/10.8/60.8, Budapest=-39.6/11.3/61.6, Bujumbura=-26.3/23.8/73.8, Bulawayo=-32.8/18.9/68.5, Burnie=-35.3/13.1/64.4, Busan=-34.8/15.0/62.8, Cabo San Lucas=-25.0/23.9/71.6, Cairns=-23.1/25.0/74.3, Cairo=-27.6/21.4/68.6, Calgary=-46.9/4.4/56.2, Canberra=-36.9/13.1/63.4, Cape Town=-33.1/16.2/63.5, Changsha=-33.3/17.4/64.8, Charlotte=-33.7/16.1/63.5, Chiang Mai=-26.4/25.8/76.2, Chicago=-39.7/9.8/60.6, Chihuahua=-33.0/18.6/72.4, Chittagong=-20.8/25.9/76.1, Chișinău=-39.5/10.2/59.2, Chongqing=-30.8/18.6/71.4, Christchurch=-37.9/12.2/62.1, City of San Marino=-40.0/11.8/64.1, Colombo=-27.2/27.4/78.0, Columbus=-39.6/11.7/63.3, Conakry=-29.0/26.4/77.7, Copenhagen=-41.2/9.1/59.8, Cotonou=-24.6/27.2/80.1, Cracow=-39.9/9.3/63.2, Da Lat=-29.9/17.9/66.6, Da Nang=-23.4/25.8/74.5, Dakar=-27.8/24.0/74.8, Dallas=-33.8/19.0/69.2, Damascus=-33.5/17.0/68.5, Dampier=-25.0/26.4/75.8, Dar es Salaam=-22.6/25.8/78.6, Darwin=-22.0/27.6/75.4, Denpasar=-24.0/23.7/76.5, Denver=-38.2/10.4/60.4, Detroit=-38.0/10.0/60.0, Dhaka=-24.9/25.9/75.7, Dikson=-59.6/-11.1/39.0, Dili=-23.6/26.6/76.5, Djibouti=-18.9/29.9/77.8, Dodoma=-26.5/22.7/73.5, Dolisie=-24.4/24.0/71.9, Douala=-23.0/26.7/77.2, Dubai=-20.8/26.9/79.8, Dublin=-38.2/9.8/62.2, Dunedin=-39.3/11.1/61.3, Durban=-26.3/20.6/73.5, Dushanbe=-33.2/14.7/66.6, Edinburgh=-45.9/9.3/58.6, Edmonton=-41.7/4.2/56.0, El Paso=-29.6/18.1/66.5, Entebbe=-27.0/21.0/72.7, Erbil=-31.8/19.5/71.9, Erzurum=-47.0/5.1/55.4, Fairbanks=-48.9/-2.3/47.3, Fianarantsoa=-33.2/17.9/68.1, Flores, Petén=-20.9/26.4/74.6, Frankfurt=-39.5/10.6/58.5, Fresno=-31.8/17.9/65.9, Fukuoka=-33.1/17.0/70.7, Gaborone=-29.0/21.0/73.1, Gabès=-34.3/19.5/70.3, Gagnoa=-24.6/26.0/80.8, Gangtok=-36.3/15.2/67.1, Garissa=-21.1/29.3/80.8, Garoua=-23.0/28.3/79.0, George Town=-23.4/27.9/78.1, Ghanzi=-33.3/21.4/73.2, Gjoa Haven=-64.9/-14.4/36.4, Guadalajara=-27.8/20.9/72.2, Guangzhou=-27.1/22.4/71.1, Guatemala City=-28.9/20.4/77.1, Halifax=-43.4/7.5/57.7, Hamburg=-41.5/9.7/65.0, Hamilton=-35.1/13.8/69.3, Hanga Roa=-29.1/20.5/70.8, Hanoi=-25.8/23.6/75.2, Harare=-33.2/18.4/69.1, Harbin=-45.1/5.0/55.0, Hargeisa=-33.4/21.7/71.1, Hat Yai=-22.5/27.0/74.3, Havana=-24.9/25.2/74.1, Helsinki=-42.3/5.9/55.2, Heraklion=-30.4/18.9/67.2, Hiroshima=-34.0/16.3/67.0, Ho Chi Minh City=-18.5/27.4/77.0, Hobart=-36.9/12.7/59.6, Hong Kong=-25.9/23.3/79.9, Honiara=-21.5/26.5/75.6, Honolulu=-22.9/25.4/73.7, Houston=-29.9/20.8/69.7, Ifrane=-36.8/11.4/59.3, Indianapolis=-39.8/11.8/58.4, Iqaluit=-58.2/-9.3/40.9, Irkutsk=-46.4/1.0/52.9, Istanbul=-35.2/13.9/61.9, Jacksonville=-29.4/20.3/72.0, Jakarta=-25.8/26.7/78.1, Jayapura=-21.2/27.0/74.9, Jerusalem=-31.8/18.3/66.8, Johannesburg=-32.2/15.5/63.9, Jos=-28.2/22.8/71.2, Juba=-21.4/27.8/76.2, Kabul=-37.5/12.1/61.9, Kampala=-33.6/20.0/70.1, Kandi=-23.3/27.7/77.6, Kankan=-24.6/26.5/82.7, Kano=-25.7/26.4/78.4, Kansas City=-38.7/12.5/60.9, Karachi=-24.5/26.0/74.4, Karonga=-22.5/24.4/77.5, Kathmandu=-37.5/18.3/67.3, Khartoum=-19.5/29.9/83.9, Kingston=-30.9/27.4/76.1, Kinshasa=-26.0/25.3/78.9, Kolkata=-23.0/26.7/76.4, Kuala Lumpur=-22.1/27.3/78.0, Kumasi=-22.4/26.0/80.3, Kunming=-33.1/15.7/66.1, Kuopio=-50.4/3.4/53.6, Kuwait City=-27.0/25.7/78.7, Kyiv=-43.4/8.4/57.5, Kyoto=-33.9/15.8/65.8, La Ceiba=-24.1/26.2/77.2, La Paz=-26.5/23.7/76.0, Lagos=-24.4/26.8/75.9, Lahore=-25.8/24.3/71.6, Lake Havasu City=-25.3/23.7/72.4, Lake Tekapo=-41.3/8.7/58.3, Las Palmas de Gran Canaria=-39.1/21.2/71.0, Las Vegas=-28.4/20.3/76.1, Launceston=-34.4/13.1/66.0, Lhasa=-41.2/7.6/57.5, Libreville=-24.0/25.9/73.8, Lisbon=-36.4/17.5/74.4, Livingstone=-27.5/21.8/77.2, Ljubljana=-36.4/10.9/61.4, Lodwar=-21.2/29.3/77.3, Lomé=-24.0/26.9/78.7, London=-38.3/11.3/63.4, Los Angeles=-29.8/18.6/67.1, Louisville=-40.0/13.9/61.7, Luanda=-22.7/25.8/75.3, Lubumbashi=-28.9/20.8/72.4, Lusaka=-29.1/19.9/75.4, Luxembourg City=-42.5/9.3/61.9, Lviv=-42.0/7.8/57.5, Lyon=-36.6/12.5/61.3, Madrid=-41.5/15.0/65.8, Mahajanga=-21.3/26.3/76.7, Makassar=-24.0/26.7/78.5, Makurdi=-21.6/26.0/76.9, Malabo=-20.1/26.3/73.1, Malé=-24.4/28.0/79.3, Managua=-26.7/27.3/78.7, Manama=-27.2/26.5/82.0, Mandalay=-22.3/28.0/76.9, Mango=-19.7/28.1/77.3, Manila=-27.7/28.4/76.9, Maputo=-31.7/22.8/71.0, Marrakesh=-28.0/19.6/74.1, Marseille=-39.0/15.8/66.1, Maun=-28.2/22.4/69.5, Medan=-24.4/26.5/78.9, Mek'ele=-28.4/22.7/73.7, Melbourne=-32.9/15.1/71.6, Memphis=-34.9/17.2/70.0, Mexicali=-31.9/23.1/71.6, Mexico City=-31.1/17.5/69.5, Miami=-24.6/24.9/75.0, Milan=-37.9/13.0/64.9, Milwaukee=-42.9/8.9/58.9, Minneapolis=-46.9/7.8/58.7, Minsk=-46.3/6.7/56.7, Mogadishu=-20.7/27.1/80.1, Mombasa=-21.4/26.3/77.4, Monaco=-34.1/16.4/66.0, Moncton=-42.7/6.1/53.7, Monterrey=-25.2/22.3/72.4, Montreal=-43.2/6.8/56.2, Moscow=-43.0/5.8/58.1, Mumbai=-22.5/27.1/78.4, Murmansk=-49.8/0.6/49.2, Muscat=-23.5/28.0/79.8, Mzuzu=-34.0/17.7/71.2, N'Djamena=-22.5/28.3/81.0, Naha=-24.9/23.1/71.0, Nairobi=-31.3/17.8/68.2, Nakhon Ratchasima=-29.4/27.3/75.4, Napier=-37.5/14.6/66.0, Napoli=-30.2/15.9/66.8, Nashville=-33.2/15.4/61.3, Nassau=-23.5/24.6/73.9, Ndola=-29.0/20.3/72.7, New Delhi=-23.4/25.0/73.4, New Orleans=-27.6/20.7/72.3, New York City=-36.1/12.9/63.9, Ngaoundéré=-25.2/22.0/73.8, Niamey=-20.5/29.3/79.3, Nicosia=-34.4/19.7/68.1, Niigata=-40.0/13.9/70.6, Nouadhibou=-27.3/21.3/76.0, Nouakchott=-23.3/25.7/84.5, Novosibirsk=-49.9/1.7/53.6, Nuuk=-52.0/-1.4/48.4, Odesa=-38.3/10.7/60.8, Odienné=-25.6/26.0/77.7, Oklahoma City=-31.5/15.9/64.4, Omaha=-38.6/10.6/57.4, Oranjestad=-24.7/28.1/78.5, Oslo=-43.8/5.7/56.2, Ottawa=-46.2/6.6/60.6, Ouagadougou=-22.3/28.3/76.2, Ouahigouya=-28.9/28.6/76.5, Ouarzazate=-32.1/18.9/66.6, Oulu=-51.5/2.7/53.0, Palembang=-20.6/27.3/76.1, Palermo=-33.8/18.5/68.3, Palm Springs=-25.4/24.5/71.9, Palmerston North=-38.8/13.2/60.8, Panama City=-22.3/28.0/76.3, Parakou=-26.4/26.8/76.6, Paris=-37.9/12.3/62.5, Perth=-29.8/18.7/67.9, Petropavlovsk-Kamchatsky=-47.7/1.9/56.0, Philadelphia=-34.1/13.2/60.1, Phnom Penh=-23.1/28.3/79.2, Phoenix=-26.8/23.9/72.6, Pittsburgh=-41.3/10.8/61.2, Podgorica=-32.4/15.3/65.3, Pointe-Noire=-24.8/26.1/74.1, Pontianak=-22.9/27.7/76.3, Port Moresby=-23.2/26.9/77.7, Port Sudan=-20.3/28.4/84.2, Port Vila=-23.2/24.3/74.7, Port-Gentil=-22.9/26.0/77.3, Portland (OR)=-36.2/12.4/61.0, Porto=-30.6/15.7/69.7, Prague=-46.5/8.4/57.3, Praia=-22.2/24.4/80.3, Pretoria=-34.0/18.2/66.9, Pyongyang=-41.5/10.8/59.6, Rabat=-34.9/17.2/68.1, Rangpur=-27.2/24.4/74.9, Reggane=-22.9/28.3/77.8, Reykjavík=-45.4/4.3/55.7, Riga=-39.8/6.2/61.3, Riyadh=-23.5/26.0/74.9, Rome=-35.5/15.2/64.5, Roseau=-22.3/26.2/81.4, Rostov-on-Don=-36.8/9.9/61.2, Sacramento=-30.9/16.3/65.1, Saint Petersburg=-43.9/5.8/54.5, Saint-Pierre=-45.1/5.7/53.5, Salt Lake City=-40.6/11.6/67.5, San Antonio=-29.7/20.8/72.8, San Diego=-31.6/17.8/69.0, San Francisco=-36.6/14.6/66.4, San Jose=-30.3/16.4/64.0, San José=-32.8/22.6/73.9, San Juan=-24.9/27.2/76.5, San Salvador=-27.9/23.1/74.4, Sana'a=-31.2/20.0/71.0, Santo Domingo=-26.5/25.9/76.4, Sapporo=-41.4/8.9/60.3, Sarajevo=-43.1/10.1/61.1, Saskatoon=-46.7/3.3/55.8, Seattle=-40.2/11.3/60.1, Seoul=-40.7/12.5/62.3, Seville=-35.5/19.2/68.8, Shanghai=-34.9/16.7/64.6, Singapore=-21.8/27.0/76.5, Skopje=-40.1/12.4/62.3, Sochi=-33.6/14.2/62.6, Sofia=-36.6/10.6/63.1, Sokoto=-21.7/28.0/76.1, Split=-33.9/16.1/63.2, St. John's=-47.5/5.0/57.9, St. Louis=-35.4/13.9/64.0, Stockholm=-43.6/6.6/57.6, Surabaya=-25.2/27.1/77.0, Suva=-26.2/25.6/74.0, Suwałki=-46.4/7.2/57.1, Sydney=-33.9/17.7/71.3, Ségou=-21.3/28.0/75.1, Tabora=-23.8/23.0/73.8, Tabriz=-40.5/12.6/63.5, Taipei=-23.5/23.0/72.8, Tallinn=-48.3/6.4/54.1, Tamale=-24.6/27.9/80.0, Tamanrasset=-26.1/21.7/70.3, Tampa=-28.4/22.9/74.7, Tashkent=-33.6/14.8/64.1, Tauranga=-37.1/14.8/69.5, Tbilisi=-40.9/12.9/63.9, Tegucigalpa=-28.9/21.7/69.4, Tehran=-36.2/17.0/70.8, Tel Aviv=-34.0/20.0/70.2, Thessaloniki=-35.1/16.0/66.3, Thiès=-23.8/24.0/70.9, Tijuana=-32.8/17.8/71.3, Timbuktu=-19.7/28.0/83.9, Tirana=-39.9/15.2/64.4, Toamasina=-30.3/23.4/72.8, Tokyo=-32.7/15.4/65.4, Toliara=-26.2/24.1/75.0, Toluca=-37.1/12.4/59.1, Toronto=-41.2/9.4/59.0, Tripoli=-32.2/20.0/66.5, Tromsø=-47.6/2.9/60.0, Tucson=-33.5/20.9/69.9, Tunis=-30.9/18.4/68.2, Ulaanbaatar=-54.1/-0.4/49.7, Upington=-27.2/20.4/78.8, Vaduz=-41.9/10.1/60.8, Valencia=-31.7/18.3/65.8, Valletta=-32.4/18.8/71.4, Vancouver=-41.1/10.4/60.9, Veracruz=-25.9/25.4/74.6, Vienna=-44.2/10.4/63.4, Vientiane=-23.2/25.9/83.4, Villahermosa=-20.0/27.1/76.7, Vilnius=-44.9/6.0/56.9, Virginia Beach=-35.9/15.8/64.7, Vladivostok=-46.3/4.9/60.2, Warsaw=-41.0/8.5/59.9, Washington, D.C.=-36.3/14.6/65.5, Wau=-20.5/27.8/79.2, Wellington=-33.0/12.9/64.0, Whitehorse=-47.5/-0.1/50.1, Wichita=-35.2/13.9/60.6, Willemstad=-21.7/28.0/77.8, Winnipeg=-51.2/3.0/53.5, Wrocław=-41.4/9.6/60.5, Xi'an=-39.7/14.1/73.7, Yakutsk=-57.8/-8.8/46.7, Yangon=-24.3/27.5/78.7, Yaoundé=-24.8/23.8/71.4, Yellowknife=-51.9/-4.3/50.0, Yerevan=-45.6/12.4/60.0, Yinchuan=-39.0/9.0/63.5, Zagreb=-41.6/10.7/58.5, Zanzibar City=-25.4/26.0/75.7, Zürich=-40.6/9.3/55.4, Ürümqi=-43.5/7.4/58.3, İzmir=-34.7/17.9/68.3}"); + } } - private static String[] fastSplit(String str) { - var splitArray = new String[2]; - var chars = str.toCharArray(); + private static List parseMeasurements(ByteBuffer byteBuffer) { + var measurements = new ArrayList(100_000); + + final int limit = byteBuffer.limit(); + final byte[] buffer = new byte[64]; + + while (byteBuffer.position() < limit) { + final int start = byteBuffer.position(); + + int separatorPosition = start; + while (separatorPosition != limit && + byteBuffer.get(separatorPosition) != ';' + ) { + separatorPosition++; + } - int i = 0; - for (char c : chars) { - if (c == ';') { - splitArray[0] = new String(Arrays.copyOfRange(chars, 0, i)); - break; + int endOfLinePosition = separatorPosition; // must be after the separator + while (endOfLinePosition != limit && + byteBuffer.get(endOfLinePosition) != '\n') { + endOfLinePosition++; } - i++; + + int nameOffset = separatorPosition - start; + byteBuffer.get(buffer, 0, nameOffset); + String key = new String(buffer, 0, nameOffset); + + byteBuffer.get(); // Get rid of th + + int valueLength = endOfLinePosition - separatorPosition - 1; + byteBuffer.get(buffer, 0, valueLength); + double value = fastParseDouble(buffer, valueLength); + + var newline = byteBuffer.get(); + if (newline == '\r') + byteBuffer.get(); + + measurements.add(new Measurement(key, value)); } - splitArray[1] = new String(Arrays.copyOfRange(chars, i + 1, chars.length)); - return splitArray; + return measurements; } - private static Double fastParseDouble(String str) { + private static double fastParseDouble(byte[] bytes, int length) { long value = 0; int exp = 0; boolean negative = false; int decimalPlaces = Integer.MIN_VALUE; - var chars = str.toCharArray(); - for (char ch : chars) { + for (int i = 0; i < length; i++) { + byte ch = bytes[i]; if (ch >= '0' && ch <= '9') { value = value * 10 + (ch - '0'); decimalPlaces++; @@ -209,5 +291,4 @@ private static double asDouble(long value, int exp, boolean negative, int decima final double d = Math.scalb((double) value, exp); return negative ? -d : d; } - } From cb710a086f566682fcb4afa78ce0a38432f3dd25 Mon Sep 17 00:00:00 2001 From: twobiers <22715034+twobiers@users.noreply.github.com> Date: Tue, 2 Jan 2024 21:28:05 +0100 Subject: [PATCH 16/18] integrate mmap --- .../onebrc/CalculateAverage_twobiers.java | 47 ++++++++++--------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java b/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java index fd12becdf..b4a81485c 100644 --- a/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java +++ b/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java @@ -105,7 +105,8 @@ public Set characteristics() { } private static class FileChannelIterator implements Iterator { - private static final long CHUNK_SIZE = (long) Math.pow(2, 19); + // File Size will be approx. 14G, 1MB Chunks sound kinda reasonable + private static final long CHUNK_SIZE = (long) Math.pow(2, 20); private final FileChannel fileChannel; private final long size; @@ -115,7 +116,8 @@ public FileChannelIterator(FileChannel fileChannel) { this.fileChannel = fileChannel; try { this.size = fileChannel.size(); - } catch (IOException e) { + } + catch (IOException e) { throw new RuntimeException(e); } } @@ -130,6 +132,7 @@ public ByteBuffer next() { try { MappedByteBuffer mappedByteBuffer = fileChannel.map(MapMode.READ_ONLY, bytesRead, Math.min(CHUNK_SIZE, size - bytesRead)); + // Ensure the chunks will end on a newline int realEnd = mappedByteBuffer.limit() - 1; while (mappedByteBuffer.get(realEnd) != '\n') { realEnd--; @@ -145,32 +148,35 @@ public ByteBuffer next() { } } - private record Measurement(String station, double value) {} + private record Measurement(String station, double value) { + } public static void main(String[] args) throws IOException { - try( - var file = new RandomAccessFile(FILE, "r"); - var channel = file.getChannel(); - ) { + try ( + var file = new RandomAccessFile(FILE, "r"); + var channel = file.getChannel();) { TreeMap measurements = StreamSupport.stream( Spliterators.spliteratorUnknownSize(new FileChannelIterator(channel), - Spliterator.IMMUTABLE), true) - .flatMap(a -> parseMeasurements(a).stream()) - .collect( - groupingBy( - Measurement::station, - TreeMap::new, - FAST_AVERAGING_COLLECTOR)); + Spliterator.IMMUTABLE), + true) + .flatMap(a -> parseMeasurements(a).stream()) + .collect( + groupingBy( + Measurement::station, + TreeMap::new, + FAST_AVERAGING_COLLECTOR)); System.out.println(measurements); // Simple test for my generated file assert measurements.toString().equals( - "{Abha=-30.1/18.0/72.2, Abidjan=-23.4/26.0/79.9, Abéché=-17.3/29.4/80.5, Accra=-24.3/26.4/77.9, Addis Ababa=-33.6/16.0/65.9, Adelaide=-33.7/17.3/71.1, Aden=-21.2/29.1/81.2, Ahvaz=-30.2/25.4/80.2, Albuquerque=-39.1/14.0/60.9, Alexandra=-36.6/11.0/62.9, Alexandria=-30.4/20.0/69.8, Algiers=-33.1/18.2/68.4, Alice Springs=-27.2/21.0/72.1, Almaty=-40.5/10.0/58.5, Amsterdam=-38.9/10.2/58.9, Anadyr=-58.2/-6.9/39.9, Anchorage=-45.3/2.8/54.3, Andorra la Vella=-42.9/9.8/60.6, Ankara=-36.7/12.0/63.7, Antananarivo=-30.9/17.9/70.8, Antsiranana=-23.0/25.2/75.4, Arkhangelsk=-48.2/1.3/51.4, Ashgabat=-30.4/17.1/64.9, Asmara=-32.6/15.6/65.4, Assab=-21.2/30.5/78.7, Astana=-45.5/3.5/49.3, Athens=-28.5/19.2/68.0, Atlanta=-33.3/17.0/69.7, Auckland=-33.6/15.2/65.0, Austin=-32.1/20.7/68.5, Baghdad=-29.6/22.8/71.6, Baguio=-29.9/19.5/68.7, Baku=-32.1/15.1/66.8, Baltimore=-36.4/13.1/62.8, Bamako=-27.0/27.8/82.0, Bangkok=-20.5/28.6/79.0, Bangui=-24.2/26.0/73.8, Banjul=-27.0/26.0/75.4, Barcelona=-36.1/18.2/74.0, Bata=-25.9/25.1/73.7, Batumi=-36.8/14.0/65.7, Beijing=-34.2/12.9/65.9, Beirut=-28.9/20.9/68.5, Belgrade=-35.7/12.5/65.5, Belize City=-24.8/26.7/75.3, Benghazi=-28.6/19.9/68.9, Bergen=-48.8/7.7/58.5, Berlin=-48.1/10.3/62.5, Bilbao=-34.5/14.7/65.2, Birao=-22.7/26.5/77.9, Bishkek=-37.2/11.3/62.1, Bissau=-24.1/27.0/82.6, Blantyre=-29.2/22.2/68.9, Bloemfontein=-32.1/15.6/66.1, Boise=-36.6/11.4/62.2, Bordeaux=-34.2/14.2/63.0, Bosaso=-20.8/30.0/77.2, Boston=-39.8/10.9/58.4, Bouaké=-24.8/26.0/76.8, Bratislava=-40.5/10.5/62.6, Brazzaville=-29.3/25.0/74.6, Bridgetown=-25.0/27.0/78.4, Brisbane=-27.2/21.4/69.7, Brussels=-37.0/10.5/56.6, Bucharest=-48.7/10.8/60.8, Budapest=-39.6/11.3/61.6, Bujumbura=-26.3/23.8/73.8, Bulawayo=-32.8/18.9/68.5, Burnie=-35.3/13.1/64.4, Busan=-34.8/15.0/62.8, Cabo San Lucas=-25.0/23.9/71.6, Cairns=-23.1/25.0/74.3, Cairo=-27.6/21.4/68.6, Calgary=-46.9/4.4/56.2, Canberra=-36.9/13.1/63.4, Cape Town=-33.1/16.2/63.5, Changsha=-33.3/17.4/64.8, Charlotte=-33.7/16.1/63.5, Chiang Mai=-26.4/25.8/76.2, Chicago=-39.7/9.8/60.6, Chihuahua=-33.0/18.6/72.4, Chittagong=-20.8/25.9/76.1, Chișinău=-39.5/10.2/59.2, Chongqing=-30.8/18.6/71.4, Christchurch=-37.9/12.2/62.1, City of San Marino=-40.0/11.8/64.1, Colombo=-27.2/27.4/78.0, Columbus=-39.6/11.7/63.3, Conakry=-29.0/26.4/77.7, Copenhagen=-41.2/9.1/59.8, Cotonou=-24.6/27.2/80.1, Cracow=-39.9/9.3/63.2, Da Lat=-29.9/17.9/66.6, Da Nang=-23.4/25.8/74.5, Dakar=-27.8/24.0/74.8, Dallas=-33.8/19.0/69.2, Damascus=-33.5/17.0/68.5, Dampier=-25.0/26.4/75.8, Dar es Salaam=-22.6/25.8/78.6, Darwin=-22.0/27.6/75.4, Denpasar=-24.0/23.7/76.5, Denver=-38.2/10.4/60.4, Detroit=-38.0/10.0/60.0, Dhaka=-24.9/25.9/75.7, Dikson=-59.6/-11.1/39.0, Dili=-23.6/26.6/76.5, Djibouti=-18.9/29.9/77.8, Dodoma=-26.5/22.7/73.5, Dolisie=-24.4/24.0/71.9, Douala=-23.0/26.7/77.2, Dubai=-20.8/26.9/79.8, Dublin=-38.2/9.8/62.2, Dunedin=-39.3/11.1/61.3, Durban=-26.3/20.6/73.5, Dushanbe=-33.2/14.7/66.6, Edinburgh=-45.9/9.3/58.6, Edmonton=-41.7/4.2/56.0, El Paso=-29.6/18.1/66.5, Entebbe=-27.0/21.0/72.7, Erbil=-31.8/19.5/71.9, Erzurum=-47.0/5.1/55.4, Fairbanks=-48.9/-2.3/47.3, Fianarantsoa=-33.2/17.9/68.1, Flores, Petén=-20.9/26.4/74.6, Frankfurt=-39.5/10.6/58.5, Fresno=-31.8/17.9/65.9, Fukuoka=-33.1/17.0/70.7, Gaborone=-29.0/21.0/73.1, Gabès=-34.3/19.5/70.3, Gagnoa=-24.6/26.0/80.8, Gangtok=-36.3/15.2/67.1, Garissa=-21.1/29.3/80.8, Garoua=-23.0/28.3/79.0, George Town=-23.4/27.9/78.1, Ghanzi=-33.3/21.4/73.2, Gjoa Haven=-64.9/-14.4/36.4, Guadalajara=-27.8/20.9/72.2, Guangzhou=-27.1/22.4/71.1, Guatemala City=-28.9/20.4/77.1, Halifax=-43.4/7.5/57.7, Hamburg=-41.5/9.7/65.0, Hamilton=-35.1/13.8/69.3, Hanga Roa=-29.1/20.5/70.8, Hanoi=-25.8/23.6/75.2, Harare=-33.2/18.4/69.1, Harbin=-45.1/5.0/55.0, Hargeisa=-33.4/21.7/71.1, Hat Yai=-22.5/27.0/74.3, Havana=-24.9/25.2/74.1, Helsinki=-42.3/5.9/55.2, Heraklion=-30.4/18.9/67.2, Hiroshima=-34.0/16.3/67.0, Ho Chi Minh City=-18.5/27.4/77.0, Hobart=-36.9/12.7/59.6, Hong Kong=-25.9/23.3/79.9, Honiara=-21.5/26.5/75.6, Honolulu=-22.9/25.4/73.7, Houston=-29.9/20.8/69.7, Ifrane=-36.8/11.4/59.3, Indianapolis=-39.8/11.8/58.4, Iqaluit=-58.2/-9.3/40.9, Irkutsk=-46.4/1.0/52.9, Istanbul=-35.2/13.9/61.9, Jacksonville=-29.4/20.3/72.0, Jakarta=-25.8/26.7/78.1, Jayapura=-21.2/27.0/74.9, Jerusalem=-31.8/18.3/66.8, Johannesburg=-32.2/15.5/63.9, Jos=-28.2/22.8/71.2, Juba=-21.4/27.8/76.2, Kabul=-37.5/12.1/61.9, Kampala=-33.6/20.0/70.1, Kandi=-23.3/27.7/77.6, Kankan=-24.6/26.5/82.7, Kano=-25.7/26.4/78.4, Kansas City=-38.7/12.5/60.9, Karachi=-24.5/26.0/74.4, Karonga=-22.5/24.4/77.5, Kathmandu=-37.5/18.3/67.3, Khartoum=-19.5/29.9/83.9, Kingston=-30.9/27.4/76.1, Kinshasa=-26.0/25.3/78.9, Kolkata=-23.0/26.7/76.4, Kuala Lumpur=-22.1/27.3/78.0, Kumasi=-22.4/26.0/80.3, Kunming=-33.1/15.7/66.1, Kuopio=-50.4/3.4/53.6, Kuwait City=-27.0/25.7/78.7, Kyiv=-43.4/8.4/57.5, Kyoto=-33.9/15.8/65.8, La Ceiba=-24.1/26.2/77.2, La Paz=-26.5/23.7/76.0, Lagos=-24.4/26.8/75.9, Lahore=-25.8/24.3/71.6, Lake Havasu City=-25.3/23.7/72.4, Lake Tekapo=-41.3/8.7/58.3, Las Palmas de Gran Canaria=-39.1/21.2/71.0, Las Vegas=-28.4/20.3/76.1, Launceston=-34.4/13.1/66.0, Lhasa=-41.2/7.6/57.5, Libreville=-24.0/25.9/73.8, Lisbon=-36.4/17.5/74.4, Livingstone=-27.5/21.8/77.2, Ljubljana=-36.4/10.9/61.4, Lodwar=-21.2/29.3/77.3, Lomé=-24.0/26.9/78.7, London=-38.3/11.3/63.4, Los Angeles=-29.8/18.6/67.1, Louisville=-40.0/13.9/61.7, Luanda=-22.7/25.8/75.3, Lubumbashi=-28.9/20.8/72.4, Lusaka=-29.1/19.9/75.4, Luxembourg City=-42.5/9.3/61.9, Lviv=-42.0/7.8/57.5, Lyon=-36.6/12.5/61.3, Madrid=-41.5/15.0/65.8, Mahajanga=-21.3/26.3/76.7, Makassar=-24.0/26.7/78.5, Makurdi=-21.6/26.0/76.9, Malabo=-20.1/26.3/73.1, Malé=-24.4/28.0/79.3, Managua=-26.7/27.3/78.7, Manama=-27.2/26.5/82.0, Mandalay=-22.3/28.0/76.9, Mango=-19.7/28.1/77.3, Manila=-27.7/28.4/76.9, Maputo=-31.7/22.8/71.0, Marrakesh=-28.0/19.6/74.1, Marseille=-39.0/15.8/66.1, Maun=-28.2/22.4/69.5, Medan=-24.4/26.5/78.9, Mek'ele=-28.4/22.7/73.7, Melbourne=-32.9/15.1/71.6, Memphis=-34.9/17.2/70.0, Mexicali=-31.9/23.1/71.6, Mexico City=-31.1/17.5/69.5, Miami=-24.6/24.9/75.0, Milan=-37.9/13.0/64.9, Milwaukee=-42.9/8.9/58.9, Minneapolis=-46.9/7.8/58.7, Minsk=-46.3/6.7/56.7, Mogadishu=-20.7/27.1/80.1, Mombasa=-21.4/26.3/77.4, Monaco=-34.1/16.4/66.0, Moncton=-42.7/6.1/53.7, Monterrey=-25.2/22.3/72.4, Montreal=-43.2/6.8/56.2, Moscow=-43.0/5.8/58.1, Mumbai=-22.5/27.1/78.4, Murmansk=-49.8/0.6/49.2, Muscat=-23.5/28.0/79.8, Mzuzu=-34.0/17.7/71.2, N'Djamena=-22.5/28.3/81.0, Naha=-24.9/23.1/71.0, Nairobi=-31.3/17.8/68.2, Nakhon Ratchasima=-29.4/27.3/75.4, Napier=-37.5/14.6/66.0, Napoli=-30.2/15.9/66.8, Nashville=-33.2/15.4/61.3, Nassau=-23.5/24.6/73.9, Ndola=-29.0/20.3/72.7, New Delhi=-23.4/25.0/73.4, New Orleans=-27.6/20.7/72.3, New York City=-36.1/12.9/63.9, Ngaoundéré=-25.2/22.0/73.8, Niamey=-20.5/29.3/79.3, Nicosia=-34.4/19.7/68.1, Niigata=-40.0/13.9/70.6, Nouadhibou=-27.3/21.3/76.0, Nouakchott=-23.3/25.7/84.5, Novosibirsk=-49.9/1.7/53.6, Nuuk=-52.0/-1.4/48.4, Odesa=-38.3/10.7/60.8, Odienné=-25.6/26.0/77.7, Oklahoma City=-31.5/15.9/64.4, Omaha=-38.6/10.6/57.4, Oranjestad=-24.7/28.1/78.5, Oslo=-43.8/5.7/56.2, Ottawa=-46.2/6.6/60.6, Ouagadougou=-22.3/28.3/76.2, Ouahigouya=-28.9/28.6/76.5, Ouarzazate=-32.1/18.9/66.6, Oulu=-51.5/2.7/53.0, Palembang=-20.6/27.3/76.1, Palermo=-33.8/18.5/68.3, Palm Springs=-25.4/24.5/71.9, Palmerston North=-38.8/13.2/60.8, Panama City=-22.3/28.0/76.3, Parakou=-26.4/26.8/76.6, Paris=-37.9/12.3/62.5, Perth=-29.8/18.7/67.9, Petropavlovsk-Kamchatsky=-47.7/1.9/56.0, Philadelphia=-34.1/13.2/60.1, Phnom Penh=-23.1/28.3/79.2, Phoenix=-26.8/23.9/72.6, Pittsburgh=-41.3/10.8/61.2, Podgorica=-32.4/15.3/65.3, Pointe-Noire=-24.8/26.1/74.1, Pontianak=-22.9/27.7/76.3, Port Moresby=-23.2/26.9/77.7, Port Sudan=-20.3/28.4/84.2, Port Vila=-23.2/24.3/74.7, Port-Gentil=-22.9/26.0/77.3, Portland (OR)=-36.2/12.4/61.0, Porto=-30.6/15.7/69.7, Prague=-46.5/8.4/57.3, Praia=-22.2/24.4/80.3, Pretoria=-34.0/18.2/66.9, Pyongyang=-41.5/10.8/59.6, Rabat=-34.9/17.2/68.1, Rangpur=-27.2/24.4/74.9, Reggane=-22.9/28.3/77.8, Reykjavík=-45.4/4.3/55.7, Riga=-39.8/6.2/61.3, Riyadh=-23.5/26.0/74.9, Rome=-35.5/15.2/64.5, Roseau=-22.3/26.2/81.4, Rostov-on-Don=-36.8/9.9/61.2, Sacramento=-30.9/16.3/65.1, Saint Petersburg=-43.9/5.8/54.5, Saint-Pierre=-45.1/5.7/53.5, Salt Lake City=-40.6/11.6/67.5, San Antonio=-29.7/20.8/72.8, San Diego=-31.6/17.8/69.0, San Francisco=-36.6/14.6/66.4, San Jose=-30.3/16.4/64.0, San José=-32.8/22.6/73.9, San Juan=-24.9/27.2/76.5, San Salvador=-27.9/23.1/74.4, Sana'a=-31.2/20.0/71.0, Santo Domingo=-26.5/25.9/76.4, Sapporo=-41.4/8.9/60.3, Sarajevo=-43.1/10.1/61.1, Saskatoon=-46.7/3.3/55.8, Seattle=-40.2/11.3/60.1, Seoul=-40.7/12.5/62.3, Seville=-35.5/19.2/68.8, Shanghai=-34.9/16.7/64.6, Singapore=-21.8/27.0/76.5, Skopje=-40.1/12.4/62.3, Sochi=-33.6/14.2/62.6, Sofia=-36.6/10.6/63.1, Sokoto=-21.7/28.0/76.1, Split=-33.9/16.1/63.2, St. John's=-47.5/5.0/57.9, St. Louis=-35.4/13.9/64.0, Stockholm=-43.6/6.6/57.6, Surabaya=-25.2/27.1/77.0, Suva=-26.2/25.6/74.0, Suwałki=-46.4/7.2/57.1, Sydney=-33.9/17.7/71.3, Ségou=-21.3/28.0/75.1, Tabora=-23.8/23.0/73.8, Tabriz=-40.5/12.6/63.5, Taipei=-23.5/23.0/72.8, Tallinn=-48.3/6.4/54.1, Tamale=-24.6/27.9/80.0, Tamanrasset=-26.1/21.7/70.3, Tampa=-28.4/22.9/74.7, Tashkent=-33.6/14.8/64.1, Tauranga=-37.1/14.8/69.5, Tbilisi=-40.9/12.9/63.9, Tegucigalpa=-28.9/21.7/69.4, Tehran=-36.2/17.0/70.8, Tel Aviv=-34.0/20.0/70.2, Thessaloniki=-35.1/16.0/66.3, Thiès=-23.8/24.0/70.9, Tijuana=-32.8/17.8/71.3, Timbuktu=-19.7/28.0/83.9, Tirana=-39.9/15.2/64.4, Toamasina=-30.3/23.4/72.8, Tokyo=-32.7/15.4/65.4, Toliara=-26.2/24.1/75.0, Toluca=-37.1/12.4/59.1, Toronto=-41.2/9.4/59.0, Tripoli=-32.2/20.0/66.5, Tromsø=-47.6/2.9/60.0, Tucson=-33.5/20.9/69.9, Tunis=-30.9/18.4/68.2, Ulaanbaatar=-54.1/-0.4/49.7, Upington=-27.2/20.4/78.8, Vaduz=-41.9/10.1/60.8, Valencia=-31.7/18.3/65.8, Valletta=-32.4/18.8/71.4, Vancouver=-41.1/10.4/60.9, Veracruz=-25.9/25.4/74.6, Vienna=-44.2/10.4/63.4, Vientiane=-23.2/25.9/83.4, Villahermosa=-20.0/27.1/76.7, Vilnius=-44.9/6.0/56.9, Virginia Beach=-35.9/15.8/64.7, Vladivostok=-46.3/4.9/60.2, Warsaw=-41.0/8.5/59.9, Washington, D.C.=-36.3/14.6/65.5, Wau=-20.5/27.8/79.2, Wellington=-33.0/12.9/64.0, Whitehorse=-47.5/-0.1/50.1, Wichita=-35.2/13.9/60.6, Willemstad=-21.7/28.0/77.8, Winnipeg=-51.2/3.0/53.5, Wrocław=-41.4/9.6/60.5, Xi'an=-39.7/14.1/73.7, Yakutsk=-57.8/-8.8/46.7, Yangon=-24.3/27.5/78.7, Yaoundé=-24.8/23.8/71.4, Yellowknife=-51.9/-4.3/50.0, Yerevan=-45.6/12.4/60.0, Yinchuan=-39.0/9.0/63.5, Zagreb=-41.6/10.7/58.5, Zanzibar City=-25.4/26.0/75.7, Zürich=-40.6/9.3/55.4, Ürümqi=-43.5/7.4/58.3, İzmir=-34.7/17.9/68.3}"); + "{Abha=-30.1/18.0/72.2, Abidjan=-23.4/26.0/79.9, Abéché=-17.3/29.4/80.5, Accra=-24.3/26.4/77.9, Addis Ababa=-33.6/16.0/65.9, Adelaide=-33.7/17.3/71.1, Aden=-21.2/29.1/81.2, Ahvaz=-30.2/25.4/80.2, Albuquerque=-39.1/14.0/60.9, Alexandra=-36.6/11.0/62.9, Alexandria=-30.4/20.0/69.8, Algiers=-33.1/18.2/68.4, Alice Springs=-27.2/21.0/72.1, Almaty=-40.5/10.0/58.5, Amsterdam=-38.9/10.2/58.9, Anadyr=-58.2/-6.9/39.9, Anchorage=-45.3/2.8/54.3, Andorra la Vella=-42.9/9.8/60.6, Ankara=-36.7/12.0/63.7, Antananarivo=-30.9/17.9/70.8, Antsiranana=-23.0/25.2/75.4, Arkhangelsk=-48.2/1.3/51.4, Ashgabat=-30.4/17.1/64.9, Asmara=-32.6/15.6/65.4, Assab=-21.2/30.5/78.7, Astana=-45.5/3.5/49.3, Athens=-28.5/19.2/68.0, Atlanta=-33.3/17.0/69.7, Auckland=-33.6/15.2/65.0, Austin=-32.1/20.7/68.5, Baghdad=-29.6/22.8/71.6, Baguio=-29.9/19.5/68.7, Baku=-32.1/15.1/66.8, Baltimore=-36.4/13.1/62.8, Bamako=-27.0/27.8/82.0, Bangkok=-20.5/28.6/79.0, Bangui=-24.2/26.0/73.8, Banjul=-27.0/26.0/75.4, Barcelona=-36.1/18.2/74.0, Bata=-25.9/25.1/73.7, Batumi=-36.8/14.0/65.7, Beijing=-34.2/12.9/65.9, Beirut=-28.9/20.9/68.5, Belgrade=-35.7/12.5/65.5, Belize City=-24.8/26.7/75.3, Benghazi=-28.6/19.9/68.9, Bergen=-48.8/7.7/58.5, Berlin=-48.1/10.3/62.5, Bilbao=-34.5/14.7/65.2, Birao=-22.7/26.5/77.9, Bishkek=-37.2/11.3/62.1, Bissau=-24.1/27.0/82.6, Blantyre=-29.2/22.2/68.9, Bloemfontein=-32.1/15.6/66.1, Boise=-36.6/11.4/62.2, Bordeaux=-34.2/14.2/63.0, Bosaso=-20.8/30.0/77.2, Boston=-39.8/10.9/58.4, Bouaké=-24.8/26.0/76.8, Bratislava=-40.5/10.5/62.6, Brazzaville=-29.3/25.0/74.6, Bridgetown=-25.0/27.0/78.4, Brisbane=-27.2/21.4/69.7, Brussels=-37.0/10.5/56.6, Bucharest=-48.7/10.8/60.8, Budapest=-39.6/11.3/61.6, Bujumbura=-26.3/23.8/73.8, Bulawayo=-32.8/18.9/68.5, Burnie=-35.3/13.1/64.4, Busan=-34.8/15.0/62.8, Cabo San Lucas=-25.0/23.9/71.6, Cairns=-23.1/25.0/74.3, Cairo=-27.6/21.4/68.6, Calgary=-46.9/4.4/56.2, Canberra=-36.9/13.1/63.4, Cape Town=-33.1/16.2/63.5, Changsha=-33.3/17.4/64.8, Charlotte=-33.7/16.1/63.5, Chiang Mai=-26.4/25.8/76.2, Chicago=-39.7/9.8/60.6, Chihuahua=-33.0/18.6/72.4, Chittagong=-20.8/25.9/76.1, Chișinău=-39.5/10.2/59.2, Chongqing=-30.8/18.6/71.4, Christchurch=-37.9/12.2/62.1, City of San Marino=-40.0/11.8/64.1, Colombo=-27.2/27.4/78.0, Columbus=-39.6/11.7/63.3, Conakry=-29.0/26.4/77.7, Copenhagen=-41.2/9.1/59.8, Cotonou=-24.6/27.2/80.1, Cracow=-39.9/9.3/63.2, Da Lat=-29.9/17.9/66.6, Da Nang=-23.4/25.8/74.5, Dakar=-27.8/24.0/74.8, Dallas=-33.8/19.0/69.2, Damascus=-33.5/17.0/68.5, Dampier=-25.0/26.4/75.8, Dar es Salaam=-22.6/25.8/78.6, Darwin=-22.0/27.6/75.4, Denpasar=-24.0/23.7/76.5, Denver=-38.2/10.4/60.4, Detroit=-38.0/10.0/60.0, Dhaka=-24.9/25.9/75.7, Dikson=-59.6/-11.1/39.0, Dili=-23.6/26.6/76.5, Djibouti=-18.9/29.9/77.8, Dodoma=-26.5/22.7/73.5, Dolisie=-24.4/24.0/71.9, Douala=-23.0/26.7/77.2, Dubai=-20.8/26.9/79.8, Dublin=-38.2/9.8/62.2, Dunedin=-39.3/11.1/61.3, Durban=-26.3/20.6/73.5, Dushanbe=-33.2/14.7/66.6, Edinburgh=-45.9/9.3/58.6, Edmonton=-41.7/4.2/56.0, El Paso=-29.6/18.1/66.5, Entebbe=-27.0/21.0/72.7, Erbil=-31.8/19.5/71.9, Erzurum=-47.0/5.1/55.4, Fairbanks=-48.9/-2.3/47.3, Fianarantsoa=-33.2/17.9/68.1, Flores, Petén=-20.9/26.4/74.6, Frankfurt=-39.5/10.6/58.5, Fresno=-31.8/17.9/65.9, Fukuoka=-33.1/17.0/70.7, Gaborone=-29.0/21.0/73.1, Gabès=-34.3/19.5/70.3, Gagnoa=-24.6/26.0/80.8, Gangtok=-36.3/15.2/67.1, Garissa=-21.1/29.3/80.8, Garoua=-23.0/28.3/79.0, George Town=-23.4/27.9/78.1, Ghanzi=-33.3/21.4/73.2, Gjoa Haven=-64.9/-14.4/36.4, Guadalajara=-27.8/20.9/72.2, Guangzhou=-27.1/22.4/71.1, Guatemala City=-28.9/20.4/77.1, Halifax=-43.4/7.5/57.7, Hamburg=-41.5/9.7/65.0, Hamilton=-35.1/13.8/69.3, Hanga Roa=-29.1/20.5/70.8, Hanoi=-25.8/23.6/75.2, Harare=-33.2/18.4/69.1, Harbin=-45.1/5.0/55.0, Hargeisa=-33.4/21.7/71.1, Hat Yai=-22.5/27.0/74.3, Havana=-24.9/25.2/74.1, Helsinki=-42.3/5.9/55.2, Heraklion=-30.4/18.9/67.2, Hiroshima=-34.0/16.3/67.0, Ho Chi Minh City=-18.5/27.4/77.0, Hobart=-36.9/12.7/59.6, Hong Kong=-25.9/23.3/79.9, Honiara=-21.5/26.5/75.6, Honolulu=-22.9/25.4/73.7, Houston=-29.9/20.8/69.7, Ifrane=-36.8/11.4/59.3, Indianapolis=-39.8/11.8/58.4, Iqaluit=-58.2/-9.3/40.9, Irkutsk=-46.4/1.0/52.9, Istanbul=-35.2/13.9/61.9, Jacksonville=-29.4/20.3/72.0, Jakarta=-25.8/26.7/78.1, Jayapura=-21.2/27.0/74.9, Jerusalem=-31.8/18.3/66.8, Johannesburg=-32.2/15.5/63.9, Jos=-28.2/22.8/71.2, Juba=-21.4/27.8/76.2, Kabul=-37.5/12.1/61.9, Kampala=-33.6/20.0/70.1, Kandi=-23.3/27.7/77.6, Kankan=-24.6/26.5/82.7, Kano=-25.7/26.4/78.4, Kansas City=-38.7/12.5/60.9, Karachi=-24.5/26.0/74.4, Karonga=-22.5/24.4/77.5, Kathmandu=-37.5/18.3/67.3, Khartoum=-19.5/29.9/83.9, Kingston=-30.9/27.4/76.1, Kinshasa=-26.0/25.3/78.9, Kolkata=-23.0/26.7/76.4, Kuala Lumpur=-22.1/27.3/78.0, Kumasi=-22.4/26.0/80.3, Kunming=-33.1/15.7/66.1, Kuopio=-50.4/3.4/53.6, Kuwait City=-27.0/25.7/78.7, Kyiv=-43.4/8.4/57.5, Kyoto=-33.9/15.8/65.8, La Ceiba=-24.1/26.2/77.2, La Paz=-26.5/23.7/76.0, Lagos=-24.4/26.8/75.9, Lahore=-25.8/24.3/71.6, Lake Havasu City=-25.3/23.7/72.4, Lake Tekapo=-41.3/8.7/58.3, Las Palmas de Gran Canaria=-39.1/21.2/71.0, Las Vegas=-28.4/20.3/76.1, Launceston=-34.4/13.1/66.0, Lhasa=-41.2/7.6/57.5, Libreville=-24.0/25.9/73.8, Lisbon=-36.4/17.5/74.4, Livingstone=-27.5/21.8/77.2, Ljubljana=-36.4/10.9/61.4, Lodwar=-21.2/29.3/77.3, Lomé=-24.0/26.9/78.7, London=-38.3/11.3/63.4, Los Angeles=-29.8/18.6/67.1, Louisville=-40.0/13.9/61.7, Luanda=-22.7/25.8/75.3, Lubumbashi=-28.9/20.8/72.4, Lusaka=-29.1/19.9/75.4, Luxembourg City=-42.5/9.3/61.9, Lviv=-42.0/7.8/57.5, Lyon=-36.6/12.5/61.3, Madrid=-41.5/15.0/65.8, Mahajanga=-21.3/26.3/76.7, Makassar=-24.0/26.7/78.5, Makurdi=-21.6/26.0/76.9, Malabo=-20.1/26.3/73.1, Malé=-24.4/28.0/79.3, Managua=-26.7/27.3/78.7, Manama=-27.2/26.5/82.0, Mandalay=-22.3/28.0/76.9, Mango=-19.7/28.1/77.3, Manila=-27.7/28.4/76.9, Maputo=-31.7/22.8/71.0, Marrakesh=-28.0/19.6/74.1, Marseille=-39.0/15.8/66.1, Maun=-28.2/22.4/69.5, Medan=-24.4/26.5/78.9, Mek'ele=-28.4/22.7/73.7, Melbourne=-32.9/15.1/71.6, Memphis=-34.9/17.2/70.0, Mexicali=-31.9/23.1/71.6, Mexico City=-31.1/17.5/69.5, Miami=-24.6/24.9/75.0, Milan=-37.9/13.0/64.9, Milwaukee=-42.9/8.9/58.9, Minneapolis=-46.9/7.8/58.7, Minsk=-46.3/6.7/56.7, Mogadishu=-20.7/27.1/80.1, Mombasa=-21.4/26.3/77.4, Monaco=-34.1/16.4/66.0, Moncton=-42.7/6.1/53.7, Monterrey=-25.2/22.3/72.4, Montreal=-43.2/6.8/56.2, Moscow=-43.0/5.8/58.1, Mumbai=-22.5/27.1/78.4, Murmansk=-49.8/0.6/49.2, Muscat=-23.5/28.0/79.8, Mzuzu=-34.0/17.7/71.2, N'Djamena=-22.5/28.3/81.0, Naha=-24.9/23.1/71.0, Nairobi=-31.3/17.8/68.2, Nakhon Ratchasima=-29.4/27.3/75.4, Napier=-37.5/14.6/66.0, Napoli=-30.2/15.9/66.8, Nashville=-33.2/15.4/61.3, Nassau=-23.5/24.6/73.9, Ndola=-29.0/20.3/72.7, New Delhi=-23.4/25.0/73.4, New Orleans=-27.6/20.7/72.3, New York City=-36.1/12.9/63.9, Ngaoundéré=-25.2/22.0/73.8, Niamey=-20.5/29.3/79.3, Nicosia=-34.4/19.7/68.1, Niigata=-40.0/13.9/70.6, Nouadhibou=-27.3/21.3/76.0, Nouakchott=-23.3/25.7/84.5, Novosibirsk=-49.9/1.7/53.6, Nuuk=-52.0/-1.4/48.4, Odesa=-38.3/10.7/60.8, Odienné=-25.6/26.0/77.7, Oklahoma City=-31.5/15.9/64.4, Omaha=-38.6/10.6/57.4, Oranjestad=-24.7/28.1/78.5, Oslo=-43.8/5.7/56.2, Ottawa=-46.2/6.6/60.6, Ouagadougou=-22.3/28.3/76.2, Ouahigouya=-28.9/28.6/76.5, Ouarzazate=-32.1/18.9/66.6, Oulu=-51.5/2.7/53.0, Palembang=-20.6/27.3/76.1, Palermo=-33.8/18.5/68.3, Palm Springs=-25.4/24.5/71.9, Palmerston North=-38.8/13.2/60.8, Panama City=-22.3/28.0/76.3, Parakou=-26.4/26.8/76.6, Paris=-37.9/12.3/62.5, Perth=-29.8/18.7/67.9, Petropavlovsk-Kamchatsky=-47.7/1.9/56.0, Philadelphia=-34.1/13.2/60.1, Phnom Penh=-23.1/28.3/79.2, Phoenix=-26.8/23.9/72.6, Pittsburgh=-41.3/10.8/61.2, Podgorica=-32.4/15.3/65.3, Pointe-Noire=-24.8/26.1/74.1, Pontianak=-22.9/27.7/76.3, Port Moresby=-23.2/26.9/77.7, Port Sudan=-20.3/28.4/84.2, Port Vila=-23.2/24.3/74.7, Port-Gentil=-22.9/26.0/77.3, Portland (OR)=-36.2/12.4/61.0, Porto=-30.6/15.7/69.7, Prague=-46.5/8.4/57.3, Praia=-22.2/24.4/80.3, Pretoria=-34.0/18.2/66.9, Pyongyang=-41.5/10.8/59.6, Rabat=-34.9/17.2/68.1, Rangpur=-27.2/24.4/74.9, Reggane=-22.9/28.3/77.8, Reykjavík=-45.4/4.3/55.7, Riga=-39.8/6.2/61.3, Riyadh=-23.5/26.0/74.9, Rome=-35.5/15.2/64.5, Roseau=-22.3/26.2/81.4, Rostov-on-Don=-36.8/9.9/61.2, Sacramento=-30.9/16.3/65.1, Saint Petersburg=-43.9/5.8/54.5, Saint-Pierre=-45.1/5.7/53.5, Salt Lake City=-40.6/11.6/67.5, San Antonio=-29.7/20.8/72.8, San Diego=-31.6/17.8/69.0, San Francisco=-36.6/14.6/66.4, San Jose=-30.3/16.4/64.0, San José=-32.8/22.6/73.9, San Juan=-24.9/27.2/76.5, San Salvador=-27.9/23.1/74.4, Sana'a=-31.2/20.0/71.0, Santo Domingo=-26.5/25.9/76.4, Sapporo=-41.4/8.9/60.3, Sarajevo=-43.1/10.1/61.1, Saskatoon=-46.7/3.3/55.8, Seattle=-40.2/11.3/60.1, Seoul=-40.7/12.5/62.3, Seville=-35.5/19.2/68.8, Shanghai=-34.9/16.7/64.6, Singapore=-21.8/27.0/76.5, Skopje=-40.1/12.4/62.3, Sochi=-33.6/14.2/62.6, Sofia=-36.6/10.6/63.1, Sokoto=-21.7/28.0/76.1, Split=-33.9/16.1/63.2, St. John's=-47.5/5.0/57.9, St. Louis=-35.4/13.9/64.0, Stockholm=-43.6/6.6/57.6, Surabaya=-25.2/27.1/77.0, Suva=-26.2/25.6/74.0, Suwałki=-46.4/7.2/57.1, Sydney=-33.9/17.7/71.3, Ségou=-21.3/28.0/75.1, Tabora=-23.8/23.0/73.8, Tabriz=-40.5/12.6/63.5, Taipei=-23.5/23.0/72.8, Tallinn=-48.3/6.4/54.1, Tamale=-24.6/27.9/80.0, Tamanrasset=-26.1/21.7/70.3, Tampa=-28.4/22.9/74.7, Tashkent=-33.6/14.8/64.1, Tauranga=-37.1/14.8/69.5, Tbilisi=-40.9/12.9/63.9, Tegucigalpa=-28.9/21.7/69.4, Tehran=-36.2/17.0/70.8, Tel Aviv=-34.0/20.0/70.2, Thessaloniki=-35.1/16.0/66.3, Thiès=-23.8/24.0/70.9, Tijuana=-32.8/17.8/71.3, Timbuktu=-19.7/28.0/83.9, Tirana=-39.9/15.2/64.4, Toamasina=-30.3/23.4/72.8, Tokyo=-32.7/15.4/65.4, Toliara=-26.2/24.1/75.0, Toluca=-37.1/12.4/59.1, Toronto=-41.2/9.4/59.0, Tripoli=-32.2/20.0/66.5, Tromsø=-47.6/2.9/60.0, Tucson=-33.5/20.9/69.9, Tunis=-30.9/18.4/68.2, Ulaanbaatar=-54.1/-0.4/49.7, Upington=-27.2/20.4/78.8, Vaduz=-41.9/10.1/60.8, Valencia=-31.7/18.3/65.8, Valletta=-32.4/18.8/71.4, Vancouver=-41.1/10.4/60.9, Veracruz=-25.9/25.4/74.6, Vienna=-44.2/10.4/63.4, Vientiane=-23.2/25.9/83.4, Villahermosa=-20.0/27.1/76.7, Vilnius=-44.9/6.0/56.9, Virginia Beach=-35.9/15.8/64.7, Vladivostok=-46.3/4.9/60.2, Warsaw=-41.0/8.5/59.9, Washington, D.C.=-36.3/14.6/65.5, Wau=-20.5/27.8/79.2, Wellington=-33.0/12.9/64.0, Whitehorse=-47.5/-0.1/50.1, Wichita=-35.2/13.9/60.6, Willemstad=-21.7/28.0/77.8, Winnipeg=-51.2/3.0/53.5, Wrocław=-41.4/9.6/60.5, Xi'an=-39.7/14.1/73.7, Yakutsk=-57.8/-8.8/46.7, Yangon=-24.3/27.5/78.7, Yaoundé=-24.8/23.8/71.4, Yellowknife=-51.9/-4.3/50.0, Yerevan=-45.6/12.4/60.0, Yinchuan=-39.0/9.0/63.5, Zagreb=-41.6/10.7/58.5, Zanzibar City=-25.4/26.0/75.7, Zürich=-40.6/9.3/55.4, Ürümqi=-43.5/7.4/58.3, İzmir=-34.7/17.9/68.3}"); } } private static List parseMeasurements(ByteBuffer byteBuffer) { + // Most of the code here is derived from @bjhara's implementation + // https://github.com/gunnarmorling/1brc/pull/10 var measurements = new ArrayList(100_000); final int limit = byteBuffer.limit(); @@ -181,14 +187,13 @@ private static List parseMeasurements(ByteBuffer byteBuffer) { int separatorPosition = start; while (separatorPosition != limit && - byteBuffer.get(separatorPosition) != ';' - ) { + byteBuffer.get(separatorPosition) != ';') { separatorPosition++; } int endOfLinePosition = separatorPosition; // must be after the separator while (endOfLinePosition != limit && - byteBuffer.get(endOfLinePosition) != '\n') { + byteBuffer.get(endOfLinePosition) != '\n') { endOfLinePosition++; } @@ -196,15 +201,13 @@ private static List parseMeasurements(ByteBuffer byteBuffer) { byteBuffer.get(buffer, 0, nameOffset); String key = new String(buffer, 0, nameOffset); - byteBuffer.get(); // Get rid of th + byteBuffer.get(); // Skip separator int valueLength = endOfLinePosition - separatorPosition - 1; byteBuffer.get(buffer, 0, valueLength); double value = fastParseDouble(buffer, valueLength); - var newline = byteBuffer.get(); - if (newline == '\r') - byteBuffer.get(); + byteBuffer.get(); // Skip newline measurements.add(new Measurement(key, value)); } From c929408ba11d1e8843304b84248d518c98121388 Mon Sep 17 00:00:00 2001 From: twobiers <22715034+twobiers@users.noreply.github.com> Date: Fri, 5 Jan 2024 19:10:52 +0100 Subject: [PATCH 17/18] Fix messed up array logic --- .../onebrc/CalculateAverage_twobiers.java | 40 +++++++++---------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java b/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java index b4a81485c..6863852b1 100644 --- a/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java +++ b/src/main/java/dev/morling/onebrc/CalculateAverage_twobiers.java @@ -47,12 +47,11 @@ public class CalculateAverage_twobiers { private static class FastAveragingCollector implements Collector { @Override public Supplier supplier() { - // 0: parsed value - // 1: current sum - // 2: count - // 4: current max - // 5: current min - return () -> new double[6]; + // 0: current sum + // 1: count + // 2: current max + // 3: current min + return () -> new double[4]; } @Override @@ -60,15 +59,14 @@ public BiConsumer accumulator() { return (a, t) -> { double val = t.value(); - a[0] = val; - a[1] += val; - a[2]++; + a[0] += val; + a[1]++; - if (val > a[4]) { - a[4] = val; + if (val > a[2] || a[1] == 1) { + a[2] = val; } - if (val < a[5]) { - a[5] = val; + if (val < a[3] || a[1] == 1) { + a[3] = val; } }; } @@ -76,13 +74,13 @@ public BiConsumer accumulator() { @Override public BinaryOperator combiner() { return (a, b) -> { - a[2] += b[2]; + a[0] += b[0]; a[1] += b[1]; - if (b[4] > a[4]) { - a[4] = b[4]; + if (b[2] > a[2]) { + a[2] = b[2]; } - if (b[5] < a[5]) { - a[5] = b[5]; + if (b[3] < a[3]) { + a[3] = b[3]; } return a; }; @@ -91,9 +89,9 @@ public BinaryOperator combiner() { @Override public Function finisher() { return a -> { - var mean = (a[2] == 0) ? 0.0d : Math.round(((a[0] + a[1]) / a[2]) * 10.0) / 10.0; - var max = a[4]; - var min = a[5]; + var mean = (a[1] == 0) ? 0.0d : Math.round((a[0] / a[1]) * 10.0) / 10.0; + var max = a[2]; + var min = a[3]; return min + "/" + mean + "/" + max; }; } From 2ec6b353503f833003e8212c71a5212d41e7b539 Mon Sep 17 00:00:00 2001 From: twobiers <22715034+twobiers@users.noreply.github.com> Date: Fri, 5 Jan 2024 19:13:16 +0100 Subject: [PATCH 18/18] Set jdk version --- calculate_average_twobiers.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/calculate_average_twobiers.sh b/calculate_average_twobiers.sh index 3d4b97d6b..8fafa3000 100755 --- a/calculate_average_twobiers.sh +++ b/calculate_average_twobiers.sh @@ -15,5 +15,7 @@ # limitations under the License. # +source "$HOME/.sdkman/bin/sdkman-init.sh" +sdk use java 21.0.1-tem 1>&2 JAVA_OPTS="-XX:+UseShenandoahGC -XX:+UseStringDeduplication -XX:+UseTransparentHugePages -da" java $JAVA_OPTS --class-path target/average-1.0.0-SNAPSHOT.jar dev.morling.onebrc.CalculateAverage_twobiers