From e79768a94534b6b345e54b908b02f3f1b4453319 Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Wed, 3 Jan 2024 17:17:34 +0000 Subject: [PATCH 1/8] Make generation pseudorandom --- .../morling/onebrc/CreateMeasurements.java | 36 ++++++++++++++----- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/src/main/java/dev/morling/onebrc/CreateMeasurements.java b/src/main/java/dev/morling/onebrc/CreateMeasurements.java index 94b3ff2db..f7a304db5 100644 --- a/src/main/java/dev/morling/onebrc/CreateMeasurements.java +++ b/src/main/java/dev/morling/onebrc/CreateMeasurements.java @@ -18,19 +18,35 @@ import java.io.BufferedWriter; import java.nio.file.Files; import java.nio.file.Path; +import java.util.Arrays; import java.util.List; import java.util.concurrent.ThreadLocalRandom; +import java.util.Random; -public class CreateMeasurements { +class WeatherStation { + private String id; + private double meanTemperature; + private Random random; - private static final Path MEASUREMENT_FILE = Path.of("./measurements.txt"); + public WeatherStation(String id, double meanTemperature) { + this.id = id; + this.meanTemperature = meanTemperature; + this.random = new Random(id.hashCode()); + } - private record WeatherStation(String id, double meanTemperature) { - double measurement() { - double m = ThreadLocalRandom.current().nextGaussian(meanTemperature, 10); - return Math.round(m * 10.0) / 10.0; - } + public String id() { + return this.id; + } + + public double measurement() { + double m = this.random.nextGaussian(this.meanTemperature, 10); + return Math.round(m * 10.0) / 10.0; } +} + +public class CreateMeasurements { + + private static final Path MEASUREMENT_FILE = Path.of("./measurements.txt"); public static void main(String[] args) throws Exception { long start = System.currentTimeMillis(); @@ -489,14 +505,16 @@ public static void main(String[] args) throws Exception { new WeatherStation("Zanzibar City", 26.0), new WeatherStation("Zürich", 9.3)); + Random random = new Random(0x3162726331627263L); try (BufferedWriter bw = Files.newBufferedWriter(MEASUREMENT_FILE)) { for (int i = 0; i < size; i++) { if (i > 0 && i % 50_000_000 == 0) { System.out.printf("Wrote %,d measurements in %s ms%n", i, System.currentTimeMillis() - start); } - WeatherStation station = stations.get(ThreadLocalRandom.current().nextInt(stations.size())); + WeatherStation station = stations.get(random.nextInt(stations.size())); bw.write(station.id()); - bw.write(";" + station.measurement()); + bw.write(";"); + bw.write(Double.toString(station.measurement())); bw.write('\n'); } } From c0bfda15478feb02f8b65594d1cdd4494a0c3fa4 Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Wed, 3 Jan 2024 17:28:31 +0000 Subject: [PATCH 2/8] Make seed configurable --- create_measurements.sh | 2 +- .../morling/onebrc/CreateMeasurements.java | 853 +++++++++--------- 2 files changed, 434 insertions(+), 421 deletions(-) diff --git a/create_measurements.sh b/create_measurements.sh index 498507223..f0dd13fd8 100755 --- a/create_measurements.sh +++ b/create_measurements.sh @@ -16,4 +16,4 @@ # -java --class-path target/average-1.0.0-SNAPSHOT.jar dev.morling.onebrc.CreateMeasurements $1 +java --class-path target/average-1.0.0-SNAPSHOT.jar dev.morling.onebrc.CreateMeasurements $1 $2 diff --git a/src/main/java/dev/morling/onebrc/CreateMeasurements.java b/src/main/java/dev/morling/onebrc/CreateMeasurements.java index f7a304db5..3ea77b1d2 100644 --- a/src/main/java/dev/morling/onebrc/CreateMeasurements.java +++ b/src/main/java/dev/morling/onebrc/CreateMeasurements.java @@ -28,10 +28,10 @@ class WeatherStation { private double meanTemperature; private Random random; - public WeatherStation(String id, double meanTemperature) { + public WeatherStation(long seed, String id, double meanTemperature) { this.id = id; this.meanTemperature = meanTemperature; - this.random = new Random(id.hashCode()); + this.random = new Random((long) id.hashCode() ^ seed); } public String id() { @@ -51,8 +51,8 @@ public class CreateMeasurements { public static void main(String[] args) throws Exception { long start = System.currentTimeMillis(); - if (args.length != 1) { - System.out.println("Usage: create_measurements.sh "); + if (args.length < 1) { + System.out.println("Usage: create_measurements.sh [seed]"); System.exit(1); } @@ -62,10 +62,23 @@ public static void main(String[] args) throws Exception { } catch (NumberFormatException e) { System.out.println("Invalid value for "); - System.out.println("Usage: CreateMeasurements "); + System.out.println("Usage: CreateMeasurements [seed]"); System.exit(1); } + // Default seed is 1brc1brc converted to hexadecimal + long seed = 0x3162726331627263L; + if (args.length == 2) { + try { + seed = Long.parseLong(args[1]); + } + catch (NumberFormatException e) { + System.out.println("Invalid value for [seed]"); + System.out.println("Usage: CreateMeasurements [seed]"); + System.exit(1); + } + } + // @formatter:off // data from https://en.wikipedia.org/wiki/List_of_cities_by_average_temperature; // converted using https://wikitable2csv.ggor.de/ @@ -90,422 +103,422 @@ public static void main(String[] args) throws Exception { // ) // ) TO 'output.csv' (HEADER, DELIMITER ','); // @formatter:on - List stations = List.of( - new WeatherStation("Abha", 18.0), - new WeatherStation("Abidjan", 26.0), - new WeatherStation("Abéché", 29.4), - new WeatherStation("Accra", 26.4), - new WeatherStation("Addis Ababa", 16.0), - new WeatherStation("Adelaide", 17.3), - new WeatherStation("Aden", 29.1), - new WeatherStation("Ahvaz", 25.4), - new WeatherStation("Albuquerque", 14.0), - new WeatherStation("Alexandra", 11.0), - new WeatherStation("Alexandria", 20.0), - new WeatherStation("Algiers", 18.2), - new WeatherStation("Alice Springs", 21.0), - new WeatherStation("Almaty", 10.0), - new WeatherStation("Amsterdam", 10.2), - new WeatherStation("Anadyr", -6.9), - new WeatherStation("Anchorage", 2.8), - new WeatherStation("Andorra la Vella", 9.8), - new WeatherStation("Ankara", 12.0), - new WeatherStation("Antananarivo", 17.9), - new WeatherStation("Antsiranana", 25.2), - new WeatherStation("Arkhangelsk", 1.3), - new WeatherStation("Ashgabat", 17.1), - new WeatherStation("Asmara", 15.6), - new WeatherStation("Assab", 30.5), - new WeatherStation("Astana", 3.5), - new WeatherStation("Athens", 19.2), - new WeatherStation("Atlanta", 17.0), - new WeatherStation("Auckland", 15.2), - new WeatherStation("Austin", 20.7), - new WeatherStation("Baghdad", 22.77), - new WeatherStation("Baguio", 19.5), - new WeatherStation("Baku", 15.1), - new WeatherStation("Baltimore", 13.1), - new WeatherStation("Bamako", 27.8), - new WeatherStation("Bangkok", 28.6), - new WeatherStation("Bangui", 26.0), - new WeatherStation("Banjul", 26.0), - new WeatherStation("Barcelona", 18.2), - new WeatherStation("Bata", 25.1), - new WeatherStation("Batumi", 14.0), - new WeatherStation("Beijing", 12.9), - new WeatherStation("Beirut", 20.9), - new WeatherStation("Belgrade", 12.5), - new WeatherStation("Belize City", 26.7), - new WeatherStation("Benghazi", 19.9), - new WeatherStation("Bergen", 7.7), - new WeatherStation("Berlin", 10.3), - new WeatherStation("Bilbao", 14.7), - new WeatherStation("Birao", 26.5), - new WeatherStation("Bishkek", 11.3), - new WeatherStation("Bissau", 27.0), - new WeatherStation("Blantyre", 22.2), - new WeatherStation("Bloemfontein", 15.6), - new WeatherStation("Boise", 11.4), - new WeatherStation("Bordeaux", 14.2), - new WeatherStation("Bosaso", 30.0), - new WeatherStation("Boston", 10.9), - new WeatherStation("Bouaké", 26.0), - new WeatherStation("Bratislava", 10.5), - new WeatherStation("Brazzaville", 25.0), - new WeatherStation("Bridgetown", 27.0), - new WeatherStation("Brisbane", 21.4), - new WeatherStation("Brussels", 10.5), - new WeatherStation("Bucharest", 10.8), - new WeatherStation("Budapest", 11.3), - new WeatherStation("Bujumbura", 23.8), - new WeatherStation("Bulawayo", 18.9), - new WeatherStation("Burnie", 13.1), - new WeatherStation("Busan", 15.0), - new WeatherStation("Cabo San Lucas", 23.9), - new WeatherStation("Cairns", 25.0), - new WeatherStation("Cairo", 21.4), - new WeatherStation("Calgary", 4.4), - new WeatherStation("Canberra", 13.1), - new WeatherStation("Cape Town", 16.2), - new WeatherStation("Changsha", 17.4), - new WeatherStation("Charlotte", 16.1), - new WeatherStation("Chiang Mai", 25.8), - new WeatherStation("Chicago", 9.8), - new WeatherStation("Chihuahua", 18.6), - new WeatherStation("Chișinău", 10.2), - new WeatherStation("Chittagong", 25.9), - new WeatherStation("Chongqing", 18.6), - new WeatherStation("Christchurch", 12.2), - new WeatherStation("City of San Marino", 11.8), - new WeatherStation("Colombo", 27.4), - new WeatherStation("Columbus", 11.7), - new WeatherStation("Conakry", 26.4), - new WeatherStation("Copenhagen", 9.1), - new WeatherStation("Cotonou", 27.2), - new WeatherStation("Cracow", 9.3), - new WeatherStation("Da Lat", 17.9), - new WeatherStation("Da Nang", 25.8), - new WeatherStation("Dakar", 24.0), - new WeatherStation("Dallas", 19.0), - new WeatherStation("Damascus", 17.0), - new WeatherStation("Dampier", 26.4), - new WeatherStation("Dar es Salaam", 25.8), - new WeatherStation("Darwin", 27.6), - new WeatherStation("Denpasar", 23.7), - new WeatherStation("Denver", 10.4), - new WeatherStation("Detroit", 10.0), - new WeatherStation("Dhaka", 25.9), - new WeatherStation("Dikson", -11.1), - new WeatherStation("Dili", 26.6), - new WeatherStation("Djibouti", 29.9), - new WeatherStation("Dodoma", 22.7), - new WeatherStation("Dolisie", 24.0), - new WeatherStation("Douala", 26.7), - new WeatherStation("Dubai", 26.9), - new WeatherStation("Dublin", 9.8), - new WeatherStation("Dunedin", 11.1), - new WeatherStation("Durban", 20.6), - new WeatherStation("Dushanbe", 14.7), - new WeatherStation("Edinburgh", 9.3), - new WeatherStation("Edmonton", 4.2), - new WeatherStation("El Paso", 18.1), - new WeatherStation("Entebbe", 21.0), - new WeatherStation("Erbil", 19.5), - new WeatherStation("Erzurum", 5.1), - new WeatherStation("Fairbanks", -2.3), - new WeatherStation("Fianarantsoa", 17.9), - new WeatherStation("Flores, Petén", 26.4), - new WeatherStation("Frankfurt", 10.6), - new WeatherStation("Fresno", 17.9), - new WeatherStation("Fukuoka", 17.0), - new WeatherStation("Gabès", 19.5), - new WeatherStation("Gaborone", 21.0), - new WeatherStation("Gagnoa", 26.0), - new WeatherStation("Gangtok", 15.2), - new WeatherStation("Garissa", 29.3), - new WeatherStation("Garoua", 28.3), - new WeatherStation("George Town", 27.9), - new WeatherStation("Ghanzi", 21.4), - new WeatherStation("Gjoa Haven", -14.4), - new WeatherStation("Guadalajara", 20.9), - new WeatherStation("Guangzhou", 22.4), - new WeatherStation("Guatemala City", 20.4), - new WeatherStation("Halifax", 7.5), - new WeatherStation("Hamburg", 9.7), - new WeatherStation("Hamilton", 13.8), - new WeatherStation("Hanga Roa", 20.5), - new WeatherStation("Hanoi", 23.6), - new WeatherStation("Harare", 18.4), - new WeatherStation("Harbin", 5.0), - new WeatherStation("Hargeisa", 21.7), - new WeatherStation("Hat Yai", 27.0), - new WeatherStation("Havana", 25.2), - new WeatherStation("Helsinki", 5.9), - new WeatherStation("Heraklion", 18.9), - new WeatherStation("Hiroshima", 16.3), - new WeatherStation("Ho Chi Minh City", 27.4), - new WeatherStation("Hobart", 12.7), - new WeatherStation("Hong Kong", 23.3), - new WeatherStation("Honiara", 26.5), - new WeatherStation("Honolulu", 25.4), - new WeatherStation("Houston", 20.8), - new WeatherStation("Ifrane", 11.4), - new WeatherStation("Indianapolis", 11.8), - new WeatherStation("Iqaluit", -9.3), - new WeatherStation("Irkutsk", 1.0), - new WeatherStation("Istanbul", 13.9), - new WeatherStation("İzmir", 17.9), - new WeatherStation("Jacksonville", 20.3), - new WeatherStation("Jakarta", 26.7), - new WeatherStation("Jayapura", 27.0), - new WeatherStation("Jerusalem", 18.3), - new WeatherStation("Johannesburg", 15.5), - new WeatherStation("Jos", 22.8), - new WeatherStation("Juba", 27.8), - new WeatherStation("Kabul", 12.1), - new WeatherStation("Kampala", 20.0), - new WeatherStation("Kandi", 27.7), - new WeatherStation("Kankan", 26.5), - new WeatherStation("Kano", 26.4), - new WeatherStation("Kansas City", 12.5), - new WeatherStation("Karachi", 26.0), - new WeatherStation("Karonga", 24.4), - new WeatherStation("Kathmandu", 18.3), - new WeatherStation("Khartoum", 29.9), - new WeatherStation("Kingston", 27.4), - new WeatherStation("Kinshasa", 25.3), - new WeatherStation("Kolkata", 26.7), - new WeatherStation("Kuala Lumpur", 27.3), - new WeatherStation("Kumasi", 26.0), - new WeatherStation("Kunming", 15.7), - new WeatherStation("Kuopio", 3.4), - new WeatherStation("Kuwait City", 25.7), - new WeatherStation("Kyiv", 8.4), - new WeatherStation("Kyoto", 15.8), - new WeatherStation("La Ceiba", 26.2), - new WeatherStation("La Paz", 23.7), - new WeatherStation("Lagos", 26.8), - new WeatherStation("Lahore", 24.3), - new WeatherStation("Lake Havasu City", 23.7), - new WeatherStation("Lake Tekapo", 8.7), - new WeatherStation("Las Palmas de Gran Canaria", 21.2), - new WeatherStation("Las Vegas", 20.3), - new WeatherStation("Launceston", 13.1), - new WeatherStation("Lhasa", 7.6), - new WeatherStation("Libreville", 25.9), - new WeatherStation("Lisbon", 17.5), - new WeatherStation("Livingstone", 21.8), - new WeatherStation("Ljubljana", 10.9), - new WeatherStation("Lodwar", 29.3), - new WeatherStation("Lomé", 26.9), - new WeatherStation("London", 11.3), - new WeatherStation("Los Angeles", 18.6), - new WeatherStation("Louisville", 13.9), - new WeatherStation("Luanda", 25.8), - new WeatherStation("Lubumbashi", 20.8), - new WeatherStation("Lusaka", 19.9), - new WeatherStation("Luxembourg City", 9.3), - new WeatherStation("Lviv", 7.8), - new WeatherStation("Lyon", 12.5), - new WeatherStation("Madrid", 15.0), - new WeatherStation("Mahajanga", 26.3), - new WeatherStation("Makassar", 26.7), - new WeatherStation("Makurdi", 26.0), - new WeatherStation("Malabo", 26.3), - new WeatherStation("Malé", 28.0), - new WeatherStation("Managua", 27.3), - new WeatherStation("Manama", 26.5), - new WeatherStation("Mandalay", 28.0), - new WeatherStation("Mango", 28.1), - new WeatherStation("Manila", 28.4), - new WeatherStation("Maputo", 22.8), - new WeatherStation("Marrakesh", 19.6), - new WeatherStation("Marseille", 15.8), - new WeatherStation("Maun", 22.4), - new WeatherStation("Medan", 26.5), - new WeatherStation("Mek'ele", 22.7), - new WeatherStation("Melbourne", 15.1), - new WeatherStation("Memphis", 17.2), - new WeatherStation("Mexicali", 23.1), - new WeatherStation("Mexico City", 17.5), - new WeatherStation("Miami", 24.9), - new WeatherStation("Milan", 13.0), - new WeatherStation("Milwaukee", 8.9), - new WeatherStation("Minneapolis", 7.8), - new WeatherStation("Minsk", 6.7), - new WeatherStation("Mogadishu", 27.1), - new WeatherStation("Mombasa", 26.3), - new WeatherStation("Monaco", 16.4), - new WeatherStation("Moncton", 6.1), - new WeatherStation("Monterrey", 22.3), - new WeatherStation("Montreal", 6.8), - new WeatherStation("Moscow", 5.8), - new WeatherStation("Mumbai", 27.1), - new WeatherStation("Murmansk", 0.6), - new WeatherStation("Muscat", 28.0), - new WeatherStation("Mzuzu", 17.7), - new WeatherStation("N'Djamena", 28.3), - new WeatherStation("Naha", 23.1), - new WeatherStation("Nairobi", 17.8), - new WeatherStation("Nakhon Ratchasima", 27.3), - new WeatherStation("Napier", 14.6), - new WeatherStation("Napoli", 15.9), - new WeatherStation("Nashville", 15.4), - new WeatherStation("Nassau", 24.6), - new WeatherStation("Ndola", 20.3), - new WeatherStation("New Delhi", 25.0), - new WeatherStation("New Orleans", 20.7), - new WeatherStation("New York City", 12.9), - new WeatherStation("Ngaoundéré", 22.0), - new WeatherStation("Niamey", 29.3), - new WeatherStation("Nicosia", 19.7), - new WeatherStation("Niigata", 13.9), - new WeatherStation("Nouadhibou", 21.3), - new WeatherStation("Nouakchott", 25.7), - new WeatherStation("Novosibirsk", 1.7), - new WeatherStation("Nuuk", -1.4), - new WeatherStation("Odesa", 10.7), - new WeatherStation("Odienné", 26.0), - new WeatherStation("Oklahoma City", 15.9), - new WeatherStation("Omaha", 10.6), - new WeatherStation("Oranjestad", 28.1), - new WeatherStation("Oslo", 5.7), - new WeatherStation("Ottawa", 6.6), - new WeatherStation("Ouagadougou", 28.3), - new WeatherStation("Ouahigouya", 28.6), - new WeatherStation("Ouarzazate", 18.9), - new WeatherStation("Oulu", 2.7), - new WeatherStation("Palembang", 27.3), - new WeatherStation("Palermo", 18.5), - new WeatherStation("Palm Springs", 24.5), - new WeatherStation("Palmerston North", 13.2), - new WeatherStation("Panama City", 28.0), - new WeatherStation("Parakou", 26.8), - new WeatherStation("Paris", 12.3), - new WeatherStation("Perth", 18.7), - new WeatherStation("Petropavlovsk-Kamchatsky", 1.9), - new WeatherStation("Philadelphia", 13.2), - new WeatherStation("Phnom Penh", 28.3), - new WeatherStation("Phoenix", 23.9), - new WeatherStation("Pittsburgh", 10.8), - new WeatherStation("Podgorica", 15.3), - new WeatherStation("Pointe-Noire", 26.1), - new WeatherStation("Pontianak", 27.7), - new WeatherStation("Port Moresby", 26.9), - new WeatherStation("Port Sudan", 28.4), - new WeatherStation("Port Vila", 24.3), - new WeatherStation("Port-Gentil", 26.0), - new WeatherStation("Portland (OR)", 12.4), - new WeatherStation("Porto", 15.7), - new WeatherStation("Prague", 8.4), - new WeatherStation("Praia", 24.4), - new WeatherStation("Pretoria", 18.2), - new WeatherStation("Pyongyang", 10.8), - new WeatherStation("Rabat", 17.2), - new WeatherStation("Rangpur", 24.4), - new WeatherStation("Reggane", 28.3), - new WeatherStation("Reykjavík", 4.3), - new WeatherStation("Riga", 6.2), - new WeatherStation("Riyadh", 26.0), - new WeatherStation("Rome", 15.2), - new WeatherStation("Roseau", 26.2), - new WeatherStation("Rostov-on-Don", 9.9), - new WeatherStation("Sacramento", 16.3), - new WeatherStation("Saint Petersburg", 5.8), - new WeatherStation("Saint-Pierre", 5.7), - new WeatherStation("Salt Lake City", 11.6), - new WeatherStation("San Antonio", 20.8), - new WeatherStation("San Diego", 17.8), - new WeatherStation("San Francisco", 14.6), - new WeatherStation("San Jose", 16.4), - new WeatherStation("San José", 22.6), - new WeatherStation("San Juan", 27.2), - new WeatherStation("San Salvador", 23.1), - new WeatherStation("Sana'a", 20.0), - new WeatherStation("Santo Domingo", 25.9), - new WeatherStation("Sapporo", 8.9), - new WeatherStation("Sarajevo", 10.1), - new WeatherStation("Saskatoon", 3.3), - new WeatherStation("Seattle", 11.3), - new WeatherStation("Ségou", 28.0), - new WeatherStation("Seoul", 12.5), - new WeatherStation("Seville", 19.2), - new WeatherStation("Shanghai", 16.7), - new WeatherStation("Singapore", 27.0), - new WeatherStation("Skopje", 12.4), - new WeatherStation("Sochi", 14.2), - new WeatherStation("Sofia", 10.6), - new WeatherStation("Sokoto", 28.0), - new WeatherStation("Split", 16.1), - new WeatherStation("St. John's", 5.0), - new WeatherStation("St. Louis", 13.9), - new WeatherStation("Stockholm", 6.6), - new WeatherStation("Surabaya", 27.1), - new WeatherStation("Suva", 25.6), - new WeatherStation("Suwałki", 7.2), - new WeatherStation("Sydney", 17.7), - new WeatherStation("Tabora", 23.0), - new WeatherStation("Tabriz", 12.6), - new WeatherStation("Taipei", 23.0), - new WeatherStation("Tallinn", 6.4), - new WeatherStation("Tamale", 27.9), - new WeatherStation("Tamanrasset", 21.7), - new WeatherStation("Tampa", 22.9), - new WeatherStation("Tashkent", 14.8), - new WeatherStation("Tauranga", 14.8), - new WeatherStation("Tbilisi", 12.9), - new WeatherStation("Tegucigalpa", 21.7), - new WeatherStation("Tehran", 17.0), - new WeatherStation("Tel Aviv", 20.0), - new WeatherStation("Thessaloniki", 16.0), - new WeatherStation("Thiès", 24.0), - new WeatherStation("Tijuana", 17.8), - new WeatherStation("Timbuktu", 28.0), - new WeatherStation("Tirana", 15.2), - new WeatherStation("Toamasina", 23.4), - new WeatherStation("Tokyo", 15.4), - new WeatherStation("Toliara", 24.1), - new WeatherStation("Toluca", 12.4), - new WeatherStation("Toronto", 9.4), - new WeatherStation("Tripoli", 20.0), - new WeatherStation("Tromsø", 2.9), - new WeatherStation("Tucson", 20.9), - new WeatherStation("Tunis", 18.4), - new WeatherStation("Ulaanbaatar", -0.4), - new WeatherStation("Upington", 20.4), - new WeatherStation("Ürümqi", 7.4), - new WeatherStation("Vaduz", 10.1), - new WeatherStation("Valencia", 18.3), - new WeatherStation("Valletta", 18.8), - new WeatherStation("Vancouver", 10.4), - new WeatherStation("Veracruz", 25.4), - new WeatherStation("Vienna", 10.4), - new WeatherStation("Vientiane", 25.9), - new WeatherStation("Villahermosa", 27.1), - new WeatherStation("Vilnius", 6.0), - new WeatherStation("Virginia Beach", 15.8), - new WeatherStation("Vladivostok", 4.9), - new WeatherStation("Warsaw", 8.5), - new WeatherStation("Washington, D.C.", 14.6), - new WeatherStation("Wau", 27.8), - new WeatherStation("Wellington", 12.9), - new WeatherStation("Whitehorse", -0.1), - new WeatherStation("Wichita", 13.9), - new WeatherStation("Willemstad", 28.0), - new WeatherStation("Winnipeg", 3.0), - new WeatherStation("Wrocław", 9.6), - new WeatherStation("Xi'an", 14.1), - new WeatherStation("Yakutsk", -8.8), - new WeatherStation("Yangon", 27.5), - new WeatherStation("Yaoundé", 23.8), - new WeatherStation("Yellowknife", -4.3), - new WeatherStation("Yerevan", 12.4), - new WeatherStation("Yinchuan", 9.0), - new WeatherStation("Zagreb", 10.7), - new WeatherStation("Zanzibar City", 26.0), - new WeatherStation("Zürich", 9.3)); + List stations = Arrays.asList( + new WeatherStation(seed, "Abha", 18.0), + new WeatherStation(seed, "Abidjan", 26.0), + new WeatherStation(seed, "Abéché", 29.4), + new WeatherStation(seed, "Accra", 26.4), + new WeatherStation(seed, "Addis Ababa", 16.0), + new WeatherStation(seed, "Adelaide", 17.3), + new WeatherStation(seed, "Aden", 29.1), + new WeatherStation(seed, "Ahvaz", 25.4), + new WeatherStation(seed, "Albuquerque", 14.0), + new WeatherStation(seed, "Alexandra", 11.0), + new WeatherStation(seed, "Alexandria", 20.0), + new WeatherStation(seed, "Algiers", 18.2), + new WeatherStation(seed, "Alice Springs", 21.0), + new WeatherStation(seed, "Almaty", 10.0), + new WeatherStation(seed, "Amsterdam", 10.2), + new WeatherStation(seed, "Anadyr", -6.9), + new WeatherStation(seed, "Anchorage", 2.8), + new WeatherStation(seed, "Andorra la Vella", 9.8), + new WeatherStation(seed, "Ankara", 12.0), + new WeatherStation(seed, "Antananarivo", 17.9), + new WeatherStation(seed, "Antsiranana", 25.2), + new WeatherStation(seed, "Arkhangelsk", 1.3), + new WeatherStation(seed, "Ashgabat", 17.1), + new WeatherStation(seed, "Asmara", 15.6), + new WeatherStation(seed, "Assab", 30.5), + new WeatherStation(seed, "Astana", 3.5), + new WeatherStation(seed, "Athens", 19.2), + new WeatherStation(seed, "Atlanta", 17.0), + new WeatherStation(seed, "Auckland", 15.2), + new WeatherStation(seed, "Austin", 20.7), + new WeatherStation(seed, "Baghdad", 22.77), + new WeatherStation(seed, "Baguio", 19.5), + new WeatherStation(seed, "Baku", 15.1), + new WeatherStation(seed, "Baltimore", 13.1), + new WeatherStation(seed, "Bamako", 27.8), + new WeatherStation(seed, "Bangkok", 28.6), + new WeatherStation(seed, "Bangui", 26.0), + new WeatherStation(seed, "Banjul", 26.0), + new WeatherStation(seed, "Barcelona", 18.2), + new WeatherStation(seed, "Bata", 25.1), + new WeatherStation(seed, "Batumi", 14.0), + new WeatherStation(seed, "Beijing", 12.9), + new WeatherStation(seed, "Beirut", 20.9), + new WeatherStation(seed, "Belgrade", 12.5), + new WeatherStation(seed, "Belize City", 26.7), + new WeatherStation(seed, "Benghazi", 19.9), + new WeatherStation(seed, "Bergen", 7.7), + new WeatherStation(seed, "Berlin", 10.3), + new WeatherStation(seed, "Bilbao", 14.7), + new WeatherStation(seed, "Birao", 26.5), + new WeatherStation(seed, "Bishkek", 11.3), + new WeatherStation(seed, "Bissau", 27.0), + new WeatherStation(seed, "Blantyre", 22.2), + new WeatherStation(seed, "Bloemfontein", 15.6), + new WeatherStation(seed, "Boise", 11.4), + new WeatherStation(seed, "Bordeaux", 14.2), + new WeatherStation(seed, "Bosaso", 30.0), + new WeatherStation(seed, "Boston", 10.9), + new WeatherStation(seed, "Bouaké", 26.0), + new WeatherStation(seed, "Bratislava", 10.5), + new WeatherStation(seed, "Brazzaville", 25.0), + new WeatherStation(seed, "Bridgetown", 27.0), + new WeatherStation(seed, "Brisbane", 21.4), + new WeatherStation(seed, "Brussels", 10.5), + new WeatherStation(seed, "Bucharest", 10.8), + new WeatherStation(seed, "Budapest", 11.3), + new WeatherStation(seed, "Bujumbura", 23.8), + new WeatherStation(seed, "Bulawayo", 18.9), + new WeatherStation(seed, "Burnie", 13.1), + new WeatherStation(seed, "Busan", 15.0), + new WeatherStation(seed, "Cabo San Lucas", 23.9), + new WeatherStation(seed, "Cairns", 25.0), + new WeatherStation(seed, "Cairo", 21.4), + new WeatherStation(seed, "Calgary", 4.4), + new WeatherStation(seed, "Canberra", 13.1), + new WeatherStation(seed, "Cape Town", 16.2), + new WeatherStation(seed, "Changsha", 17.4), + new WeatherStation(seed, "Charlotte", 16.1), + new WeatherStation(seed, "Chiang Mai", 25.8), + new WeatherStation(seed, "Chicago", 9.8), + new WeatherStation(seed, "Chihuahua", 18.6), + new WeatherStation(seed, "Chișinău", 10.2), + new WeatherStation(seed, "Chittagong", 25.9), + new WeatherStation(seed, "Chongqing", 18.6), + new WeatherStation(seed, "Christchurch", 12.2), + new WeatherStation(seed, "City of San Marino", 11.8), + new WeatherStation(seed, "Colombo", 27.4), + new WeatherStation(seed, "Columbus", 11.7), + new WeatherStation(seed, "Conakry", 26.4), + new WeatherStation(seed, "Copenhagen", 9.1), + new WeatherStation(seed, "Cotonou", 27.2), + new WeatherStation(seed, "Cracow", 9.3), + new WeatherStation(seed, "Da Lat", 17.9), + new WeatherStation(seed, "Da Nang", 25.8), + new WeatherStation(seed, "Dakar", 24.0), + new WeatherStation(seed, "Dallas", 19.0), + new WeatherStation(seed, "Damascus", 17.0), + new WeatherStation(seed, "Dampier", 26.4), + new WeatherStation(seed, "Dar es Salaam", 25.8), + new WeatherStation(seed, "Darwin", 27.6), + new WeatherStation(seed, "Denpasar", 23.7), + new WeatherStation(seed, "Denver", 10.4), + new WeatherStation(seed, "Detroit", 10.0), + new WeatherStation(seed, "Dhaka", 25.9), + new WeatherStation(seed, "Dikson", -11.1), + new WeatherStation(seed, "Dili", 26.6), + new WeatherStation(seed, "Djibouti", 29.9), + new WeatherStation(seed, "Dodoma", 22.7), + new WeatherStation(seed, "Dolisie", 24.0), + new WeatherStation(seed, "Douala", 26.7), + new WeatherStation(seed, "Dubai", 26.9), + new WeatherStation(seed, "Dublin", 9.8), + new WeatherStation(seed, "Dunedin", 11.1), + new WeatherStation(seed, "Durban", 20.6), + new WeatherStation(seed, "Dushanbe", 14.7), + new WeatherStation(seed, "Edinburgh", 9.3), + new WeatherStation(seed, "Edmonton", 4.2), + new WeatherStation(seed, "El Paso", 18.1), + new WeatherStation(seed, "Entebbe", 21.0), + new WeatherStation(seed, "Erbil", 19.5), + new WeatherStation(seed, "Erzurum", 5.1), + new WeatherStation(seed, "Fairbanks", -2.3), + new WeatherStation(seed, "Fianarantsoa", 17.9), + new WeatherStation(seed, "Flores, Petén", 26.4), + new WeatherStation(seed, "Frankfurt", 10.6), + new WeatherStation(seed, "Fresno", 17.9), + new WeatherStation(seed, "Fukuoka", 17.0), + new WeatherStation(seed, "Gabès", 19.5), + new WeatherStation(seed, "Gaborone", 21.0), + new WeatherStation(seed, "Gagnoa", 26.0), + new WeatherStation(seed, "Gangtok", 15.2), + new WeatherStation(seed, "Garissa", 29.3), + new WeatherStation(seed, "Garoua", 28.3), + new WeatherStation(seed, "George Town", 27.9), + new WeatherStation(seed, "Ghanzi", 21.4), + new WeatherStation(seed, "Gjoa Haven", -14.4), + new WeatherStation(seed, "Guadalajara", 20.9), + new WeatherStation(seed, "Guangzhou", 22.4), + new WeatherStation(seed, "Guatemala City", 20.4), + new WeatherStation(seed, "Halifax", 7.5), + new WeatherStation(seed, "Hamburg", 9.7), + new WeatherStation(seed, "Hamilton", 13.8), + new WeatherStation(seed, "Hanga Roa", 20.5), + new WeatherStation(seed, "Hanoi", 23.6), + new WeatherStation(seed, "Harare", 18.4), + new WeatherStation(seed, "Harbin", 5.0), + new WeatherStation(seed, "Hargeisa", 21.7), + new WeatherStation(seed, "Hat Yai", 27.0), + new WeatherStation(seed, "Havana", 25.2), + new WeatherStation(seed, "Helsinki", 5.9), + new WeatherStation(seed, "Heraklion", 18.9), + new WeatherStation(seed, "Hiroshima", 16.3), + new WeatherStation(seed, "Ho Chi Minh City", 27.4), + new WeatherStation(seed, "Hobart", 12.7), + new WeatherStation(seed, "Hong Kong", 23.3), + new WeatherStation(seed, "Honiara", 26.5), + new WeatherStation(seed, "Honolulu", 25.4), + new WeatherStation(seed, "Houston", 20.8), + new WeatherStation(seed, "Ifrane", 11.4), + new WeatherStation(seed, "Indianapolis", 11.8), + new WeatherStation(seed, "Iqaluit", -9.3), + new WeatherStation(seed, "Irkutsk", 1.0), + new WeatherStation(seed, "Istanbul", 13.9), + new WeatherStation(seed, "İzmir", 17.9), + new WeatherStation(seed, "Jacksonville", 20.3), + new WeatherStation(seed, "Jakarta", 26.7), + new WeatherStation(seed, "Jayapura", 27.0), + new WeatherStation(seed, "Jerusalem", 18.3), + new WeatherStation(seed, "Johannesburg", 15.5), + new WeatherStation(seed, "Jos", 22.8), + new WeatherStation(seed, "Juba", 27.8), + new WeatherStation(seed, "Kabul", 12.1), + new WeatherStation(seed, "Kampala", 20.0), + new WeatherStation(seed, "Kandi", 27.7), + new WeatherStation(seed, "Kankan", 26.5), + new WeatherStation(seed, "Kano", 26.4), + new WeatherStation(seed, "Kansas City", 12.5), + new WeatherStation(seed, "Karachi", 26.0), + new WeatherStation(seed, "Karonga", 24.4), + new WeatherStation(seed, "Kathmandu", 18.3), + new WeatherStation(seed, "Khartoum", 29.9), + new WeatherStation(seed, "Kingston", 27.4), + new WeatherStation(seed, "Kinshasa", 25.3), + new WeatherStation(seed, "Kolkata", 26.7), + new WeatherStation(seed, "Kuala Lumpur", 27.3), + new WeatherStation(seed, "Kumasi", 26.0), + new WeatherStation(seed, "Kunming", 15.7), + new WeatherStation(seed, "Kuopio", 3.4), + new WeatherStation(seed, "Kuwait City", 25.7), + new WeatherStation(seed, "Kyiv", 8.4), + new WeatherStation(seed, "Kyoto", 15.8), + new WeatherStation(seed, "La Ceiba", 26.2), + new WeatherStation(seed, "La Paz", 23.7), + new WeatherStation(seed, "Lagos", 26.8), + new WeatherStation(seed, "Lahore", 24.3), + new WeatherStation(seed, "Lake Havasu City", 23.7), + new WeatherStation(seed, "Lake Tekapo", 8.7), + new WeatherStation(seed, "Las Palmas de Gran Canaria", 21.2), + new WeatherStation(seed, "Las Vegas", 20.3), + new WeatherStation(seed, "Launceston", 13.1), + new WeatherStation(seed, "Lhasa", 7.6), + new WeatherStation(seed, "Libreville", 25.9), + new WeatherStation(seed, "Lisbon", 17.5), + new WeatherStation(seed, "Livingstone", 21.8), + new WeatherStation(seed, "Ljubljana", 10.9), + new WeatherStation(seed, "Lodwar", 29.3), + new WeatherStation(seed, "Lomé", 26.9), + new WeatherStation(seed, "London", 11.3), + new WeatherStation(seed, "Los Angeles", 18.6), + new WeatherStation(seed, "Louisville", 13.9), + new WeatherStation(seed, "Luanda", 25.8), + new WeatherStation(seed, "Lubumbashi", 20.8), + new WeatherStation(seed, "Lusaka", 19.9), + new WeatherStation(seed, "Luxembourg City", 9.3), + new WeatherStation(seed, "Lviv", 7.8), + new WeatherStation(seed, "Lyon", 12.5), + new WeatherStation(seed, "Madrid", 15.0), + new WeatherStation(seed, "Mahajanga", 26.3), + new WeatherStation(seed, "Makassar", 26.7), + new WeatherStation(seed, "Makurdi", 26.0), + new WeatherStation(seed, "Malabo", 26.3), + new WeatherStation(seed, "Malé", 28.0), + new WeatherStation(seed, "Managua", 27.3), + new WeatherStation(seed, "Manama", 26.5), + new WeatherStation(seed, "Mandalay", 28.0), + new WeatherStation(seed, "Mango", 28.1), + new WeatherStation(seed, "Manila", 28.4), + new WeatherStation(seed, "Maputo", 22.8), + new WeatherStation(seed, "Marrakesh", 19.6), + new WeatherStation(seed, "Marseille", 15.8), + new WeatherStation(seed, "Maun", 22.4), + new WeatherStation(seed, "Medan", 26.5), + new WeatherStation(seed, "Mek'ele", 22.7), + new WeatherStation(seed, "Melbourne", 15.1), + new WeatherStation(seed, "Memphis", 17.2), + new WeatherStation(seed, "Mexicali", 23.1), + new WeatherStation(seed, "Mexico City", 17.5), + new WeatherStation(seed, "Miami", 24.9), + new WeatherStation(seed, "Milan", 13.0), + new WeatherStation(seed, "Milwaukee", 8.9), + new WeatherStation(seed, "Minneapolis", 7.8), + new WeatherStation(seed, "Minsk", 6.7), + new WeatherStation(seed, "Mogadishu", 27.1), + new WeatherStation(seed, "Mombasa", 26.3), + new WeatherStation(seed, "Monaco", 16.4), + new WeatherStation(seed, "Moncton", 6.1), + new WeatherStation(seed, "Monterrey", 22.3), + new WeatherStation(seed, "Montreal", 6.8), + new WeatherStation(seed, "Moscow", 5.8), + new WeatherStation(seed, "Mumbai", 27.1), + new WeatherStation(seed, "Murmansk", 0.6), + new WeatherStation(seed, "Muscat", 28.0), + new WeatherStation(seed, "Mzuzu", 17.7), + new WeatherStation(seed, "N'Djamena", 28.3), + new WeatherStation(seed, "Naha", 23.1), + new WeatherStation(seed, "Nairobi", 17.8), + new WeatherStation(seed, "Nakhon Ratchasima", 27.3), + new WeatherStation(seed, "Napier", 14.6), + new WeatherStation(seed, "Napoli", 15.9), + new WeatherStation(seed, "Nashville", 15.4), + new WeatherStation(seed, "Nassau", 24.6), + new WeatherStation(seed, "Ndola", 20.3), + new WeatherStation(seed, "New Delhi", 25.0), + new WeatherStation(seed, "New Orleans", 20.7), + new WeatherStation(seed, "New York City", 12.9), + new WeatherStation(seed, "Ngaoundéré", 22.0), + new WeatherStation(seed, "Niamey", 29.3), + new WeatherStation(seed, "Nicosia", 19.7), + new WeatherStation(seed, "Niigata", 13.9), + new WeatherStation(seed, "Nouadhibou", 21.3), + new WeatherStation(seed, "Nouakchott", 25.7), + new WeatherStation(seed, "Novosibirsk", 1.7), + new WeatherStation(seed, "Nuuk", -1.4), + new WeatherStation(seed, "Odesa", 10.7), + new WeatherStation(seed, "Odienné", 26.0), + new WeatherStation(seed, "Oklahoma City", 15.9), + new WeatherStation(seed, "Omaha", 10.6), + new WeatherStation(seed, "Oranjestad", 28.1), + new WeatherStation(seed, "Oslo", 5.7), + new WeatherStation(seed, "Ottawa", 6.6), + new WeatherStation(seed, "Ouagadougou", 28.3), + new WeatherStation(seed, "Ouahigouya", 28.6), + new WeatherStation(seed, "Ouarzazate", 18.9), + new WeatherStation(seed, "Oulu", 2.7), + new WeatherStation(seed, "Palembang", 27.3), + new WeatherStation(seed, "Palermo", 18.5), + new WeatherStation(seed, "Palm Springs", 24.5), + new WeatherStation(seed, "Palmerston North", 13.2), + new WeatherStation(seed, "Panama City", 28.0), + new WeatherStation(seed, "Parakou", 26.8), + new WeatherStation(seed, "Paris", 12.3), + new WeatherStation(seed, "Perth", 18.7), + new WeatherStation(seed, "Petropavlovsk-Kamchatsky", 1.9), + new WeatherStation(seed, "Philadelphia", 13.2), + new WeatherStation(seed, "Phnom Penh", 28.3), + new WeatherStation(seed, "Phoenix", 23.9), + new WeatherStation(seed, "Pittsburgh", 10.8), + new WeatherStation(seed, "Podgorica", 15.3), + new WeatherStation(seed, "Pointe-Noire", 26.1), + new WeatherStation(seed, "Pontianak", 27.7), + new WeatherStation(seed, "Port Moresby", 26.9), + new WeatherStation(seed, "Port Sudan", 28.4), + new WeatherStation(seed, "Port Vila", 24.3), + new WeatherStation(seed, "Port-Gentil", 26.0), + new WeatherStation(seed, "Portland (OR)", 12.4), + new WeatherStation(seed, "Porto", 15.7), + new WeatherStation(seed, "Prague", 8.4), + new WeatherStation(seed, "Praia", 24.4), + new WeatherStation(seed, "Pretoria", 18.2), + new WeatherStation(seed, "Pyongyang", 10.8), + new WeatherStation(seed, "Rabat", 17.2), + new WeatherStation(seed, "Rangpur", 24.4), + new WeatherStation(seed, "Reggane", 28.3), + new WeatherStation(seed, "Reykjavík", 4.3), + new WeatherStation(seed, "Riga", 6.2), + new WeatherStation(seed, "Riyadh", 26.0), + new WeatherStation(seed, "Rome", 15.2), + new WeatherStation(seed, "Roseau", 26.2), + new WeatherStation(seed, "Rostov-on-Don", 9.9), + new WeatherStation(seed, "Sacramento", 16.3), + new WeatherStation(seed, "Saint Petersburg", 5.8), + new WeatherStation(seed, "Saint-Pierre", 5.7), + new WeatherStation(seed, "Salt Lake City", 11.6), + new WeatherStation(seed, "San Antonio", 20.8), + new WeatherStation(seed, "San Diego", 17.8), + new WeatherStation(seed, "San Francisco", 14.6), + new WeatherStation(seed, "San Jose", 16.4), + new WeatherStation(seed, "San José", 22.6), + new WeatherStation(seed, "San Juan", 27.2), + new WeatherStation(seed, "San Salvador", 23.1), + new WeatherStation(seed, "Sana'a", 20.0), + new WeatherStation(seed, "Santo Domingo", 25.9), + new WeatherStation(seed, "Sapporo", 8.9), + new WeatherStation(seed, "Sarajevo", 10.1), + new WeatherStation(seed, "Saskatoon", 3.3), + new WeatherStation(seed, "Seattle", 11.3), + new WeatherStation(seed, "Ségou", 28.0), + new WeatherStation(seed, "Seoul", 12.5), + new WeatherStation(seed, "Seville", 19.2), + new WeatherStation(seed, "Shanghai", 16.7), + new WeatherStation(seed, "Singapore", 27.0), + new WeatherStation(seed, "Skopje", 12.4), + new WeatherStation(seed, "Sochi", 14.2), + new WeatherStation(seed, "Sofia", 10.6), + new WeatherStation(seed, "Sokoto", 28.0), + new WeatherStation(seed, "Split", 16.1), + new WeatherStation(seed, "St. John's", 5.0), + new WeatherStation(seed, "St. Louis", 13.9), + new WeatherStation(seed, "Stockholm", 6.6), + new WeatherStation(seed, "Surabaya", 27.1), + new WeatherStation(seed, "Suva", 25.6), + new WeatherStation(seed, "Suwałki", 7.2), + new WeatherStation(seed, "Sydney", 17.7), + new WeatherStation(seed, "Tabora", 23.0), + new WeatherStation(seed, "Tabriz", 12.6), + new WeatherStation(seed, "Taipei", 23.0), + new WeatherStation(seed, "Tallinn", 6.4), + new WeatherStation(seed, "Tamale", 27.9), + new WeatherStation(seed, "Tamanrasset", 21.7), + new WeatherStation(seed, "Tampa", 22.9), + new WeatherStation(seed, "Tashkent", 14.8), + new WeatherStation(seed, "Tauranga", 14.8), + new WeatherStation(seed, "Tbilisi", 12.9), + new WeatherStation(seed, "Tegucigalpa", 21.7), + new WeatherStation(seed, "Tehran", 17.0), + new WeatherStation(seed, "Tel Aviv", 20.0), + new WeatherStation(seed, "Thessaloniki", 16.0), + new WeatherStation(seed, "Thiès", 24.0), + new WeatherStation(seed, "Tijuana", 17.8), + new WeatherStation(seed, "Timbuktu", 28.0), + new WeatherStation(seed, "Tirana", 15.2), + new WeatherStation(seed, "Toamasina", 23.4), + new WeatherStation(seed, "Tokyo", 15.4), + new WeatherStation(seed, "Toliara", 24.1), + new WeatherStation(seed, "Toluca", 12.4), + new WeatherStation(seed, "Toronto", 9.4), + new WeatherStation(seed, "Tripoli", 20.0), + new WeatherStation(seed, "Tromsø", 2.9), + new WeatherStation(seed, "Tucson", 20.9), + new WeatherStation(seed, "Tunis", 18.4), + new WeatherStation(seed, "Ulaanbaatar", -0.4), + new WeatherStation(seed, "Upington", 20.4), + new WeatherStation(seed, "Ürümqi", 7.4), + new WeatherStation(seed, "Vaduz", 10.1), + new WeatherStation(seed, "Valencia", 18.3), + new WeatherStation(seed, "Valletta", 18.8), + new WeatherStation(seed, "Vancouver", 10.4), + new WeatherStation(seed, "Veracruz", 25.4), + new WeatherStation(seed, "Vienna", 10.4), + new WeatherStation(seed, "Vientiane", 25.9), + new WeatherStation(seed, "Villahermosa", 27.1), + new WeatherStation(seed, "Vilnius", 6.0), + new WeatherStation(seed, "Virginia Beach", 15.8), + new WeatherStation(seed, "Vladivostok", 4.9), + new WeatherStation(seed, "Warsaw", 8.5), + new WeatherStation(seed, "Washington, D.C.", 14.6), + new WeatherStation(seed, "Wau", 27.8), + new WeatherStation(seed, "Wellington", 12.9), + new WeatherStation(seed, "Whitehorse", -0.1), + new WeatherStation(seed, "Wichita", 13.9), + new WeatherStation(seed, "Willemstad", 28.0), + new WeatherStation(seed, "Winnipeg", 3.0), + new WeatherStation(seed, "Wrocław", 9.6), + new WeatherStation(seed, "Xi'an", 14.1), + new WeatherStation(seed, "Yakutsk", -8.8), + new WeatherStation(seed, "Yangon", 27.5), + new WeatherStation(seed, "Yaoundé", 23.8), + new WeatherStation(seed, "Yellowknife", -4.3), + new WeatherStation(seed, "Yerevan", 12.4), + new WeatherStation(seed, "Yinchuan", 9.0), + new WeatherStation(seed, "Zagreb", 10.7), + new WeatherStation(seed, "Zanzibar City", 26.0), + new WeatherStation(seed, "Zürich", 9.3)); - Random random = new Random(0x3162726331627263L); + Random random = new Random(seed); try (BufferedWriter bw = Files.newBufferedWriter(MEASUREMENT_FILE)) { for (int i = 0; i < size; i++) { if (i > 0 && i % 50_000_000 == 0) { From 4aafab2fd4c8b512e4f0ad6193d5c9edd16ac192 Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Fri, 5 Jan 2024 18:09:49 +0000 Subject: [PATCH 3/8] Deduplicate WeatherStation class --- .../morling/onebrc/CreateMeasurements.java | 462 +---------------- .../morling/onebrc/CreateMeasurements2.java | 477 +----------------- .../dev/morling/onebrc/WeatherStation.java | 69 +++ .../morling/onebrc/WeatherStationFactory.java | 472 +++++++++++++++++ 4 files changed, 544 insertions(+), 936 deletions(-) create mode 100644 src/main/java/dev/morling/onebrc/WeatherStation.java create mode 100644 src/main/java/dev/morling/onebrc/WeatherStationFactory.java diff --git a/src/main/java/dev/morling/onebrc/CreateMeasurements.java b/src/main/java/dev/morling/onebrc/CreateMeasurements.java index 3ea77b1d2..68575ab53 100644 --- a/src/main/java/dev/morling/onebrc/CreateMeasurements.java +++ b/src/main/java/dev/morling/onebrc/CreateMeasurements.java @@ -23,27 +23,6 @@ import java.util.concurrent.ThreadLocalRandom; import java.util.Random; -class WeatherStation { - private String id; - private double meanTemperature; - private Random random; - - public WeatherStation(long seed, String id, double meanTemperature) { - this.id = id; - this.meanTemperature = meanTemperature; - this.random = new Random((long) id.hashCode() ^ seed); - } - - public String id() { - return this.id; - } - - public double measurement() { - double m = this.random.nextGaussian(this.meanTemperature, 10); - return Math.round(m * 10.0) / 10.0; - } -} - public class CreateMeasurements { private static final Path MEASUREMENT_FILE = Path.of("./measurements.txt"); @@ -79,444 +58,7 @@ public static void main(String[] args) throws Exception { } } - // @formatter:off - // data from https://en.wikipedia.org/wiki/List_of_cities_by_average_temperature; - // converted using https://wikitable2csv.ggor.de/ - // brought to form using DuckDB: - // D copy ( - // select City, regexp_extract(Year,'(.*)\n.*', 1) as AverageTemp - // from ( - // select City,Year - // from read_csv_auto('List_of_cities_by_average_temperature_1.csv', header = true) - // union - // select City,Year - // from read_csv_auto('List_of_cities_by_average_temperature_2.csv', header = true) - // union - // select City,Year - // from read_csv_auto('List_of_cities_by_average_temperature_3.csv', header = true) - // union - // select City,Year - // from read_csv_auto('List_of_cities_by_average_temperature_4.csv', header = true) - // union - // select City,Year - // from read_csv_auto('List_of_cities_by_average_temperature_5.csv', header = true) - // ) - // ) TO 'output.csv' (HEADER, DELIMITER ','); - // @formatter:on - List stations = Arrays.asList( - new WeatherStation(seed, "Abha", 18.0), - new WeatherStation(seed, "Abidjan", 26.0), - new WeatherStation(seed, "Abéché", 29.4), - new WeatherStation(seed, "Accra", 26.4), - new WeatherStation(seed, "Addis Ababa", 16.0), - new WeatherStation(seed, "Adelaide", 17.3), - new WeatherStation(seed, "Aden", 29.1), - new WeatherStation(seed, "Ahvaz", 25.4), - new WeatherStation(seed, "Albuquerque", 14.0), - new WeatherStation(seed, "Alexandra", 11.0), - new WeatherStation(seed, "Alexandria", 20.0), - new WeatherStation(seed, "Algiers", 18.2), - new WeatherStation(seed, "Alice Springs", 21.0), - new WeatherStation(seed, "Almaty", 10.0), - new WeatherStation(seed, "Amsterdam", 10.2), - new WeatherStation(seed, "Anadyr", -6.9), - new WeatherStation(seed, "Anchorage", 2.8), - new WeatherStation(seed, "Andorra la Vella", 9.8), - new WeatherStation(seed, "Ankara", 12.0), - new WeatherStation(seed, "Antananarivo", 17.9), - new WeatherStation(seed, "Antsiranana", 25.2), - new WeatherStation(seed, "Arkhangelsk", 1.3), - new WeatherStation(seed, "Ashgabat", 17.1), - new WeatherStation(seed, "Asmara", 15.6), - new WeatherStation(seed, "Assab", 30.5), - new WeatherStation(seed, "Astana", 3.5), - new WeatherStation(seed, "Athens", 19.2), - new WeatherStation(seed, "Atlanta", 17.0), - new WeatherStation(seed, "Auckland", 15.2), - new WeatherStation(seed, "Austin", 20.7), - new WeatherStation(seed, "Baghdad", 22.77), - new WeatherStation(seed, "Baguio", 19.5), - new WeatherStation(seed, "Baku", 15.1), - new WeatherStation(seed, "Baltimore", 13.1), - new WeatherStation(seed, "Bamako", 27.8), - new WeatherStation(seed, "Bangkok", 28.6), - new WeatherStation(seed, "Bangui", 26.0), - new WeatherStation(seed, "Banjul", 26.0), - new WeatherStation(seed, "Barcelona", 18.2), - new WeatherStation(seed, "Bata", 25.1), - new WeatherStation(seed, "Batumi", 14.0), - new WeatherStation(seed, "Beijing", 12.9), - new WeatherStation(seed, "Beirut", 20.9), - new WeatherStation(seed, "Belgrade", 12.5), - new WeatherStation(seed, "Belize City", 26.7), - new WeatherStation(seed, "Benghazi", 19.9), - new WeatherStation(seed, "Bergen", 7.7), - new WeatherStation(seed, "Berlin", 10.3), - new WeatherStation(seed, "Bilbao", 14.7), - new WeatherStation(seed, "Birao", 26.5), - new WeatherStation(seed, "Bishkek", 11.3), - new WeatherStation(seed, "Bissau", 27.0), - new WeatherStation(seed, "Blantyre", 22.2), - new WeatherStation(seed, "Bloemfontein", 15.6), - new WeatherStation(seed, "Boise", 11.4), - new WeatherStation(seed, "Bordeaux", 14.2), - new WeatherStation(seed, "Bosaso", 30.0), - new WeatherStation(seed, "Boston", 10.9), - new WeatherStation(seed, "Bouaké", 26.0), - new WeatherStation(seed, "Bratislava", 10.5), - new WeatherStation(seed, "Brazzaville", 25.0), - new WeatherStation(seed, "Bridgetown", 27.0), - new WeatherStation(seed, "Brisbane", 21.4), - new WeatherStation(seed, "Brussels", 10.5), - new WeatherStation(seed, "Bucharest", 10.8), - new WeatherStation(seed, "Budapest", 11.3), - new WeatherStation(seed, "Bujumbura", 23.8), - new WeatherStation(seed, "Bulawayo", 18.9), - new WeatherStation(seed, "Burnie", 13.1), - new WeatherStation(seed, "Busan", 15.0), - new WeatherStation(seed, "Cabo San Lucas", 23.9), - new WeatherStation(seed, "Cairns", 25.0), - new WeatherStation(seed, "Cairo", 21.4), - new WeatherStation(seed, "Calgary", 4.4), - new WeatherStation(seed, "Canberra", 13.1), - new WeatherStation(seed, "Cape Town", 16.2), - new WeatherStation(seed, "Changsha", 17.4), - new WeatherStation(seed, "Charlotte", 16.1), - new WeatherStation(seed, "Chiang Mai", 25.8), - new WeatherStation(seed, "Chicago", 9.8), - new WeatherStation(seed, "Chihuahua", 18.6), - new WeatherStation(seed, "Chișinău", 10.2), - new WeatherStation(seed, "Chittagong", 25.9), - new WeatherStation(seed, "Chongqing", 18.6), - new WeatherStation(seed, "Christchurch", 12.2), - new WeatherStation(seed, "City of San Marino", 11.8), - new WeatherStation(seed, "Colombo", 27.4), - new WeatherStation(seed, "Columbus", 11.7), - new WeatherStation(seed, "Conakry", 26.4), - new WeatherStation(seed, "Copenhagen", 9.1), - new WeatherStation(seed, "Cotonou", 27.2), - new WeatherStation(seed, "Cracow", 9.3), - new WeatherStation(seed, "Da Lat", 17.9), - new WeatherStation(seed, "Da Nang", 25.8), - new WeatherStation(seed, "Dakar", 24.0), - new WeatherStation(seed, "Dallas", 19.0), - new WeatherStation(seed, "Damascus", 17.0), - new WeatherStation(seed, "Dampier", 26.4), - new WeatherStation(seed, "Dar es Salaam", 25.8), - new WeatherStation(seed, "Darwin", 27.6), - new WeatherStation(seed, "Denpasar", 23.7), - new WeatherStation(seed, "Denver", 10.4), - new WeatherStation(seed, "Detroit", 10.0), - new WeatherStation(seed, "Dhaka", 25.9), - new WeatherStation(seed, "Dikson", -11.1), - new WeatherStation(seed, "Dili", 26.6), - new WeatherStation(seed, "Djibouti", 29.9), - new WeatherStation(seed, "Dodoma", 22.7), - new WeatherStation(seed, "Dolisie", 24.0), - new WeatherStation(seed, "Douala", 26.7), - new WeatherStation(seed, "Dubai", 26.9), - new WeatherStation(seed, "Dublin", 9.8), - new WeatherStation(seed, "Dunedin", 11.1), - new WeatherStation(seed, "Durban", 20.6), - new WeatherStation(seed, "Dushanbe", 14.7), - new WeatherStation(seed, "Edinburgh", 9.3), - new WeatherStation(seed, "Edmonton", 4.2), - new WeatherStation(seed, "El Paso", 18.1), - new WeatherStation(seed, "Entebbe", 21.0), - new WeatherStation(seed, "Erbil", 19.5), - new WeatherStation(seed, "Erzurum", 5.1), - new WeatherStation(seed, "Fairbanks", -2.3), - new WeatherStation(seed, "Fianarantsoa", 17.9), - new WeatherStation(seed, "Flores, Petén", 26.4), - new WeatherStation(seed, "Frankfurt", 10.6), - new WeatherStation(seed, "Fresno", 17.9), - new WeatherStation(seed, "Fukuoka", 17.0), - new WeatherStation(seed, "Gabès", 19.5), - new WeatherStation(seed, "Gaborone", 21.0), - new WeatherStation(seed, "Gagnoa", 26.0), - new WeatherStation(seed, "Gangtok", 15.2), - new WeatherStation(seed, "Garissa", 29.3), - new WeatherStation(seed, "Garoua", 28.3), - new WeatherStation(seed, "George Town", 27.9), - new WeatherStation(seed, "Ghanzi", 21.4), - new WeatherStation(seed, "Gjoa Haven", -14.4), - new WeatherStation(seed, "Guadalajara", 20.9), - new WeatherStation(seed, "Guangzhou", 22.4), - new WeatherStation(seed, "Guatemala City", 20.4), - new WeatherStation(seed, "Halifax", 7.5), - new WeatherStation(seed, "Hamburg", 9.7), - new WeatherStation(seed, "Hamilton", 13.8), - new WeatherStation(seed, "Hanga Roa", 20.5), - new WeatherStation(seed, "Hanoi", 23.6), - new WeatherStation(seed, "Harare", 18.4), - new WeatherStation(seed, "Harbin", 5.0), - new WeatherStation(seed, "Hargeisa", 21.7), - new WeatherStation(seed, "Hat Yai", 27.0), - new WeatherStation(seed, "Havana", 25.2), - new WeatherStation(seed, "Helsinki", 5.9), - new WeatherStation(seed, "Heraklion", 18.9), - new WeatherStation(seed, "Hiroshima", 16.3), - new WeatherStation(seed, "Ho Chi Minh City", 27.4), - new WeatherStation(seed, "Hobart", 12.7), - new WeatherStation(seed, "Hong Kong", 23.3), - new WeatherStation(seed, "Honiara", 26.5), - new WeatherStation(seed, "Honolulu", 25.4), - new WeatherStation(seed, "Houston", 20.8), - new WeatherStation(seed, "Ifrane", 11.4), - new WeatherStation(seed, "Indianapolis", 11.8), - new WeatherStation(seed, "Iqaluit", -9.3), - new WeatherStation(seed, "Irkutsk", 1.0), - new WeatherStation(seed, "Istanbul", 13.9), - new WeatherStation(seed, "İzmir", 17.9), - new WeatherStation(seed, "Jacksonville", 20.3), - new WeatherStation(seed, "Jakarta", 26.7), - new WeatherStation(seed, "Jayapura", 27.0), - new WeatherStation(seed, "Jerusalem", 18.3), - new WeatherStation(seed, "Johannesburg", 15.5), - new WeatherStation(seed, "Jos", 22.8), - new WeatherStation(seed, "Juba", 27.8), - new WeatherStation(seed, "Kabul", 12.1), - new WeatherStation(seed, "Kampala", 20.0), - new WeatherStation(seed, "Kandi", 27.7), - new WeatherStation(seed, "Kankan", 26.5), - new WeatherStation(seed, "Kano", 26.4), - new WeatherStation(seed, "Kansas City", 12.5), - new WeatherStation(seed, "Karachi", 26.0), - new WeatherStation(seed, "Karonga", 24.4), - new WeatherStation(seed, "Kathmandu", 18.3), - new WeatherStation(seed, "Khartoum", 29.9), - new WeatherStation(seed, "Kingston", 27.4), - new WeatherStation(seed, "Kinshasa", 25.3), - new WeatherStation(seed, "Kolkata", 26.7), - new WeatherStation(seed, "Kuala Lumpur", 27.3), - new WeatherStation(seed, "Kumasi", 26.0), - new WeatherStation(seed, "Kunming", 15.7), - new WeatherStation(seed, "Kuopio", 3.4), - new WeatherStation(seed, "Kuwait City", 25.7), - new WeatherStation(seed, "Kyiv", 8.4), - new WeatherStation(seed, "Kyoto", 15.8), - new WeatherStation(seed, "La Ceiba", 26.2), - new WeatherStation(seed, "La Paz", 23.7), - new WeatherStation(seed, "Lagos", 26.8), - new WeatherStation(seed, "Lahore", 24.3), - new WeatherStation(seed, "Lake Havasu City", 23.7), - new WeatherStation(seed, "Lake Tekapo", 8.7), - new WeatherStation(seed, "Las Palmas de Gran Canaria", 21.2), - new WeatherStation(seed, "Las Vegas", 20.3), - new WeatherStation(seed, "Launceston", 13.1), - new WeatherStation(seed, "Lhasa", 7.6), - new WeatherStation(seed, "Libreville", 25.9), - new WeatherStation(seed, "Lisbon", 17.5), - new WeatherStation(seed, "Livingstone", 21.8), - new WeatherStation(seed, "Ljubljana", 10.9), - new WeatherStation(seed, "Lodwar", 29.3), - new WeatherStation(seed, "Lomé", 26.9), - new WeatherStation(seed, "London", 11.3), - new WeatherStation(seed, "Los Angeles", 18.6), - new WeatherStation(seed, "Louisville", 13.9), - new WeatherStation(seed, "Luanda", 25.8), - new WeatherStation(seed, "Lubumbashi", 20.8), - new WeatherStation(seed, "Lusaka", 19.9), - new WeatherStation(seed, "Luxembourg City", 9.3), - new WeatherStation(seed, "Lviv", 7.8), - new WeatherStation(seed, "Lyon", 12.5), - new WeatherStation(seed, "Madrid", 15.0), - new WeatherStation(seed, "Mahajanga", 26.3), - new WeatherStation(seed, "Makassar", 26.7), - new WeatherStation(seed, "Makurdi", 26.0), - new WeatherStation(seed, "Malabo", 26.3), - new WeatherStation(seed, "Malé", 28.0), - new WeatherStation(seed, "Managua", 27.3), - new WeatherStation(seed, "Manama", 26.5), - new WeatherStation(seed, "Mandalay", 28.0), - new WeatherStation(seed, "Mango", 28.1), - new WeatherStation(seed, "Manila", 28.4), - new WeatherStation(seed, "Maputo", 22.8), - new WeatherStation(seed, "Marrakesh", 19.6), - new WeatherStation(seed, "Marseille", 15.8), - new WeatherStation(seed, "Maun", 22.4), - new WeatherStation(seed, "Medan", 26.5), - new WeatherStation(seed, "Mek'ele", 22.7), - new WeatherStation(seed, "Melbourne", 15.1), - new WeatherStation(seed, "Memphis", 17.2), - new WeatherStation(seed, "Mexicali", 23.1), - new WeatherStation(seed, "Mexico City", 17.5), - new WeatherStation(seed, "Miami", 24.9), - new WeatherStation(seed, "Milan", 13.0), - new WeatherStation(seed, "Milwaukee", 8.9), - new WeatherStation(seed, "Minneapolis", 7.8), - new WeatherStation(seed, "Minsk", 6.7), - new WeatherStation(seed, "Mogadishu", 27.1), - new WeatherStation(seed, "Mombasa", 26.3), - new WeatherStation(seed, "Monaco", 16.4), - new WeatherStation(seed, "Moncton", 6.1), - new WeatherStation(seed, "Monterrey", 22.3), - new WeatherStation(seed, "Montreal", 6.8), - new WeatherStation(seed, "Moscow", 5.8), - new WeatherStation(seed, "Mumbai", 27.1), - new WeatherStation(seed, "Murmansk", 0.6), - new WeatherStation(seed, "Muscat", 28.0), - new WeatherStation(seed, "Mzuzu", 17.7), - new WeatherStation(seed, "N'Djamena", 28.3), - new WeatherStation(seed, "Naha", 23.1), - new WeatherStation(seed, "Nairobi", 17.8), - new WeatherStation(seed, "Nakhon Ratchasima", 27.3), - new WeatherStation(seed, "Napier", 14.6), - new WeatherStation(seed, "Napoli", 15.9), - new WeatherStation(seed, "Nashville", 15.4), - new WeatherStation(seed, "Nassau", 24.6), - new WeatherStation(seed, "Ndola", 20.3), - new WeatherStation(seed, "New Delhi", 25.0), - new WeatherStation(seed, "New Orleans", 20.7), - new WeatherStation(seed, "New York City", 12.9), - new WeatherStation(seed, "Ngaoundéré", 22.0), - new WeatherStation(seed, "Niamey", 29.3), - new WeatherStation(seed, "Nicosia", 19.7), - new WeatherStation(seed, "Niigata", 13.9), - new WeatherStation(seed, "Nouadhibou", 21.3), - new WeatherStation(seed, "Nouakchott", 25.7), - new WeatherStation(seed, "Novosibirsk", 1.7), - new WeatherStation(seed, "Nuuk", -1.4), - new WeatherStation(seed, "Odesa", 10.7), - new WeatherStation(seed, "Odienné", 26.0), - new WeatherStation(seed, "Oklahoma City", 15.9), - new WeatherStation(seed, "Omaha", 10.6), - new WeatherStation(seed, "Oranjestad", 28.1), - new WeatherStation(seed, "Oslo", 5.7), - new WeatherStation(seed, "Ottawa", 6.6), - new WeatherStation(seed, "Ouagadougou", 28.3), - new WeatherStation(seed, "Ouahigouya", 28.6), - new WeatherStation(seed, "Ouarzazate", 18.9), - new WeatherStation(seed, "Oulu", 2.7), - new WeatherStation(seed, "Palembang", 27.3), - new WeatherStation(seed, "Palermo", 18.5), - new WeatherStation(seed, "Palm Springs", 24.5), - new WeatherStation(seed, "Palmerston North", 13.2), - new WeatherStation(seed, "Panama City", 28.0), - new WeatherStation(seed, "Parakou", 26.8), - new WeatherStation(seed, "Paris", 12.3), - new WeatherStation(seed, "Perth", 18.7), - new WeatherStation(seed, "Petropavlovsk-Kamchatsky", 1.9), - new WeatherStation(seed, "Philadelphia", 13.2), - new WeatherStation(seed, "Phnom Penh", 28.3), - new WeatherStation(seed, "Phoenix", 23.9), - new WeatherStation(seed, "Pittsburgh", 10.8), - new WeatherStation(seed, "Podgorica", 15.3), - new WeatherStation(seed, "Pointe-Noire", 26.1), - new WeatherStation(seed, "Pontianak", 27.7), - new WeatherStation(seed, "Port Moresby", 26.9), - new WeatherStation(seed, "Port Sudan", 28.4), - new WeatherStation(seed, "Port Vila", 24.3), - new WeatherStation(seed, "Port-Gentil", 26.0), - new WeatherStation(seed, "Portland (OR)", 12.4), - new WeatherStation(seed, "Porto", 15.7), - new WeatherStation(seed, "Prague", 8.4), - new WeatherStation(seed, "Praia", 24.4), - new WeatherStation(seed, "Pretoria", 18.2), - new WeatherStation(seed, "Pyongyang", 10.8), - new WeatherStation(seed, "Rabat", 17.2), - new WeatherStation(seed, "Rangpur", 24.4), - new WeatherStation(seed, "Reggane", 28.3), - new WeatherStation(seed, "Reykjavík", 4.3), - new WeatherStation(seed, "Riga", 6.2), - new WeatherStation(seed, "Riyadh", 26.0), - new WeatherStation(seed, "Rome", 15.2), - new WeatherStation(seed, "Roseau", 26.2), - new WeatherStation(seed, "Rostov-on-Don", 9.9), - new WeatherStation(seed, "Sacramento", 16.3), - new WeatherStation(seed, "Saint Petersburg", 5.8), - new WeatherStation(seed, "Saint-Pierre", 5.7), - new WeatherStation(seed, "Salt Lake City", 11.6), - new WeatherStation(seed, "San Antonio", 20.8), - new WeatherStation(seed, "San Diego", 17.8), - new WeatherStation(seed, "San Francisco", 14.6), - new WeatherStation(seed, "San Jose", 16.4), - new WeatherStation(seed, "San José", 22.6), - new WeatherStation(seed, "San Juan", 27.2), - new WeatherStation(seed, "San Salvador", 23.1), - new WeatherStation(seed, "Sana'a", 20.0), - new WeatherStation(seed, "Santo Domingo", 25.9), - new WeatherStation(seed, "Sapporo", 8.9), - new WeatherStation(seed, "Sarajevo", 10.1), - new WeatherStation(seed, "Saskatoon", 3.3), - new WeatherStation(seed, "Seattle", 11.3), - new WeatherStation(seed, "Ségou", 28.0), - new WeatherStation(seed, "Seoul", 12.5), - new WeatherStation(seed, "Seville", 19.2), - new WeatherStation(seed, "Shanghai", 16.7), - new WeatherStation(seed, "Singapore", 27.0), - new WeatherStation(seed, "Skopje", 12.4), - new WeatherStation(seed, "Sochi", 14.2), - new WeatherStation(seed, "Sofia", 10.6), - new WeatherStation(seed, "Sokoto", 28.0), - new WeatherStation(seed, "Split", 16.1), - new WeatherStation(seed, "St. John's", 5.0), - new WeatherStation(seed, "St. Louis", 13.9), - new WeatherStation(seed, "Stockholm", 6.6), - new WeatherStation(seed, "Surabaya", 27.1), - new WeatherStation(seed, "Suva", 25.6), - new WeatherStation(seed, "Suwałki", 7.2), - new WeatherStation(seed, "Sydney", 17.7), - new WeatherStation(seed, "Tabora", 23.0), - new WeatherStation(seed, "Tabriz", 12.6), - new WeatherStation(seed, "Taipei", 23.0), - new WeatherStation(seed, "Tallinn", 6.4), - new WeatherStation(seed, "Tamale", 27.9), - new WeatherStation(seed, "Tamanrasset", 21.7), - new WeatherStation(seed, "Tampa", 22.9), - new WeatherStation(seed, "Tashkent", 14.8), - new WeatherStation(seed, "Tauranga", 14.8), - new WeatherStation(seed, "Tbilisi", 12.9), - new WeatherStation(seed, "Tegucigalpa", 21.7), - new WeatherStation(seed, "Tehran", 17.0), - new WeatherStation(seed, "Tel Aviv", 20.0), - new WeatherStation(seed, "Thessaloniki", 16.0), - new WeatherStation(seed, "Thiès", 24.0), - new WeatherStation(seed, "Tijuana", 17.8), - new WeatherStation(seed, "Timbuktu", 28.0), - new WeatherStation(seed, "Tirana", 15.2), - new WeatherStation(seed, "Toamasina", 23.4), - new WeatherStation(seed, "Tokyo", 15.4), - new WeatherStation(seed, "Toliara", 24.1), - new WeatherStation(seed, "Toluca", 12.4), - new WeatherStation(seed, "Toronto", 9.4), - new WeatherStation(seed, "Tripoli", 20.0), - new WeatherStation(seed, "Tromsø", 2.9), - new WeatherStation(seed, "Tucson", 20.9), - new WeatherStation(seed, "Tunis", 18.4), - new WeatherStation(seed, "Ulaanbaatar", -0.4), - new WeatherStation(seed, "Upington", 20.4), - new WeatherStation(seed, "Ürümqi", 7.4), - new WeatherStation(seed, "Vaduz", 10.1), - new WeatherStation(seed, "Valencia", 18.3), - new WeatherStation(seed, "Valletta", 18.8), - new WeatherStation(seed, "Vancouver", 10.4), - new WeatherStation(seed, "Veracruz", 25.4), - new WeatherStation(seed, "Vienna", 10.4), - new WeatherStation(seed, "Vientiane", 25.9), - new WeatherStation(seed, "Villahermosa", 27.1), - new WeatherStation(seed, "Vilnius", 6.0), - new WeatherStation(seed, "Virginia Beach", 15.8), - new WeatherStation(seed, "Vladivostok", 4.9), - new WeatherStation(seed, "Warsaw", 8.5), - new WeatherStation(seed, "Washington, D.C.", 14.6), - new WeatherStation(seed, "Wau", 27.8), - new WeatherStation(seed, "Wellington", 12.9), - new WeatherStation(seed, "Whitehorse", -0.1), - new WeatherStation(seed, "Wichita", 13.9), - new WeatherStation(seed, "Willemstad", 28.0), - new WeatherStation(seed, "Winnipeg", 3.0), - new WeatherStation(seed, "Wrocław", 9.6), - new WeatherStation(seed, "Xi'an", 14.1), - new WeatherStation(seed, "Yakutsk", -8.8), - new WeatherStation(seed, "Yangon", 27.5), - new WeatherStation(seed, "Yaoundé", 23.8), - new WeatherStation(seed, "Yellowknife", -4.3), - new WeatherStation(seed, "Yerevan", 12.4), - new WeatherStation(seed, "Yinchuan", 9.0), - new WeatherStation(seed, "Zagreb", 10.7), - new WeatherStation(seed, "Zanzibar City", 26.0), - new WeatherStation(seed, "Zürich", 9.3)); + List stations = WeatherStationFactory.getWeatherStationsList(seed); Random random = new Random(seed); try (BufferedWriter bw = Files.newBufferedWriter(MEASUREMENT_FILE)) { @@ -525,7 +67,7 @@ public static void main(String[] args) throws Exception { System.out.printf("Wrote %,d measurements in %s ms%n", i, System.currentTimeMillis() - start); } WeatherStation station = stations.get(random.nextInt(stations.size())); - bw.write(station.id()); + bw.write(station.id); bw.write(";"); bw.write(Double.toString(station.measurement())); bw.write('\n'); diff --git a/src/main/java/dev/morling/onebrc/CreateMeasurements2.java b/src/main/java/dev/morling/onebrc/CreateMeasurements2.java index e12e3f91e..e9898f1b2 100644 --- a/src/main/java/dev/morling/onebrc/CreateMeasurements2.java +++ b/src/main/java/dev/morling/onebrc/CreateMeasurements2.java @@ -34,44 +34,6 @@ public class CreateMeasurements2 { private static final String FILE = "./measurements2.txt"; - static class WeatherStation { - final static char[] NUMBERS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; - - final String id; - final int meanTemperature; - - final char[] firstPart; - final FastRandom r = new FastRandom(ThreadLocalRandom.current().nextLong()); - - WeatherStation(String id, double meanTemperature) { - this.id = id; - this.meanTemperature = (int) meanTemperature; - // make it directly copyable - this.firstPart = (id + ";").toCharArray(); - } - - /** - * We write out data into the buffer to avoid string conversion - * We also no longer use double and gaussian, because for our - * purpose, the fake numbers here will do it. Less - * - * @param buffer the buffer to append to - */ - void measurement(final CheaperCharBuffer buffer) { - // fake -10.9 to +10.9 variance without double operations and rounding - // gives us -10 to +10 - int m = meanTemperature + (r.nextInt(21) - 10); - // gives us a decimal digit 0 to 9 as char - char d = NUMBERS[r.nextInt(10)]; - - // just append, only one number has to be converted and we can do - // better... if we watn - buffer.append(firstPart, 0, firstPart.length) - .append(String.valueOf(m)).append('.').append(d) - .append('\n'); - } - } - public static void main(String[] args) throws Exception { long start = System.currentTimeMillis(); @@ -90,444 +52,7 @@ public static void main(String[] args) throws Exception { System.exit(1); } - // @formatter:off - // data from https://en.wikipedia.org/wiki/List_of_cities_by_average_temperature; - // converted using https://wikitable2csv.ggor.de/ - // brought to form using DuckDB: - // D copy ( - // select City, regexp_extract(Year,'(.*)\n.*', 1) as AverageTemp - // from ( - // select City,Year - // from read_csv_auto('List_of_cities_by_average_temperature_1.csv', header = true) - // union - // select City,Year - // from read_csv_auto('List_of_cities_by_average_temperature_2.csv', header = true) - // union - // select City,Year - // from read_csv_auto('List_of_cities_by_average_temperature_3.csv', header = true) - // union - // select City,Year - // from read_csv_auto('List_of_cities_by_average_temperature_4.csv', header = true) - // union - // select City,Year - // from read_csv_auto('List_of_cities_by_average_temperature_5.csv', header = true) - // ) - // ) TO 'output.csv' (HEADER, DELIMITER ','); - // @formatter:on - final List stations = Arrays.asList( - new WeatherStation("Abha", 18.0), - new WeatherStation("Abidjan", 26.0), - new WeatherStation("Abéché", 29.4), - new WeatherStation("Accra", 26.4), - new WeatherStation("Addis Ababa", 16.0), - new WeatherStation("Adelaide", 17.3), - new WeatherStation("Aden", 29.1), - new WeatherStation("Ahvaz", 25.4), - new WeatherStation("Albuquerque", 14.0), - new WeatherStation("Alexandra", 11.0), - new WeatherStation("Alexandria", 20.0), - new WeatherStation("Algiers", 18.2), - new WeatherStation("Alice Springs", 21.0), - new WeatherStation("Almaty", 10.0), - new WeatherStation("Amsterdam", 10.2), - new WeatherStation("Anadyr", -6.9), - new WeatherStation("Anchorage", 2.8), - new WeatherStation("Andorra la Vella", 9.8), - new WeatherStation("Ankara", 12.0), - new WeatherStation("Antananarivo", 17.9), - new WeatherStation("Antsiranana", 25.2), - new WeatherStation("Arkhangelsk", 1.3), - new WeatherStation("Ashgabat", 17.1), - new WeatherStation("Asmara", 15.6), - new WeatherStation("Assab", 30.5), - new WeatherStation("Astana", 3.5), - new WeatherStation("Athens", 19.2), - new WeatherStation("Atlanta", 17.0), - new WeatherStation("Auckland", 15.2), - new WeatherStation("Austin", 20.7), - new WeatherStation("Baghdad", 22.77), - new WeatherStation("Baguio", 19.5), - new WeatherStation("Baku", 15.1), - new WeatherStation("Baltimore", 13.1), - new WeatherStation("Bamako", 27.8), - new WeatherStation("Bangkok", 28.6), - new WeatherStation("Bangui", 26.0), - new WeatherStation("Banjul", 26.0), - new WeatherStation("Barcelona", 18.2), - new WeatherStation("Bata", 25.1), - new WeatherStation("Batumi", 14.0), - new WeatherStation("Beijing", 12.9), - new WeatherStation("Beirut", 20.9), - new WeatherStation("Belgrade", 12.5), - new WeatherStation("Belize City", 26.7), - new WeatherStation("Benghazi", 19.9), - new WeatherStation("Bergen", 7.7), - new WeatherStation("Berlin", 10.3), - new WeatherStation("Bilbao", 14.7), - new WeatherStation("Birao", 26.5), - new WeatherStation("Bishkek", 11.3), - new WeatherStation("Bissau", 27.0), - new WeatherStation("Blantyre", 22.2), - new WeatherStation("Bloemfontein", 15.6), - new WeatherStation("Boise", 11.4), - new WeatherStation("Bordeaux", 14.2), - new WeatherStation("Bosaso", 30.0), - new WeatherStation("Boston", 10.9), - new WeatherStation("Bouaké", 26.0), - new WeatherStation("Bratislava", 10.5), - new WeatherStation("Brazzaville", 25.0), - new WeatherStation("Bridgetown", 27.0), - new WeatherStation("Brisbane", 21.4), - new WeatherStation("Brussels", 10.5), - new WeatherStation("Bucharest", 10.8), - new WeatherStation("Budapest", 11.3), - new WeatherStation("Bujumbura", 23.8), - new WeatherStation("Bulawayo", 18.9), - new WeatherStation("Burnie", 13.1), - new WeatherStation("Busan", 15.0), - new WeatherStation("Cabo San Lucas", 23.9), - new WeatherStation("Cairns", 25.0), - new WeatherStation("Cairo", 21.4), - new WeatherStation("Calgary", 4.4), - new WeatherStation("Canberra", 13.1), - new WeatherStation("Cape Town", 16.2), - new WeatherStation("Changsha", 17.4), - new WeatherStation("Charlotte", 16.1), - new WeatherStation("Chiang Mai", 25.8), - new WeatherStation("Chicago", 9.8), - new WeatherStation("Chihuahua", 18.6), - new WeatherStation("Chișinău", 10.2), - new WeatherStation("Chittagong", 25.9), - new WeatherStation("Chongqing", 18.6), - new WeatherStation("Christchurch", 12.2), - new WeatherStation("City of San Marino", 11.8), - new WeatherStation("Colombo", 27.4), - new WeatherStation("Columbus", 11.7), - new WeatherStation("Conakry", 26.4), - new WeatherStation("Copenhagen", 9.1), - new WeatherStation("Cotonou", 27.2), - new WeatherStation("Cracow", 9.3), - new WeatherStation("Da Lat", 17.9), - new WeatherStation("Da Nang", 25.8), - new WeatherStation("Dakar", 24.0), - new WeatherStation("Dallas", 19.0), - new WeatherStation("Damascus", 17.0), - new WeatherStation("Dampier", 26.4), - new WeatherStation("Dar es Salaam", 25.8), - new WeatherStation("Darwin", 27.6), - new WeatherStation("Denpasar", 23.7), - new WeatherStation("Denver", 10.4), - new WeatherStation("Detroit", 10.0), - new WeatherStation("Dhaka", 25.9), - new WeatherStation("Dikson", -11.1), - new WeatherStation("Dili", 26.6), - new WeatherStation("Djibouti", 29.9), - new WeatherStation("Dodoma", 22.7), - new WeatherStation("Dolisie", 24.0), - new WeatherStation("Douala", 26.7), - new WeatherStation("Dubai", 26.9), - new WeatherStation("Dublin", 9.8), - new WeatherStation("Dunedin", 11.1), - new WeatherStation("Durban", 20.6), - new WeatherStation("Dushanbe", 14.7), - new WeatherStation("Edinburgh", 9.3), - new WeatherStation("Edmonton", 4.2), - new WeatherStation("El Paso", 18.1), - new WeatherStation("Entebbe", 21.0), - new WeatherStation("Erbil", 19.5), - new WeatherStation("Erzurum", 5.1), - new WeatherStation("Fairbanks", -2.3), - new WeatherStation("Fianarantsoa", 17.9), - new WeatherStation("Flores, Petén", 26.4), - new WeatherStation("Frankfurt", 10.6), - new WeatherStation("Fresno", 17.9), - new WeatherStation("Fukuoka", 17.0), - new WeatherStation("Gabès", 19.5), - new WeatherStation("Gaborone", 21.0), - new WeatherStation("Gagnoa", 26.0), - new WeatherStation("Gangtok", 15.2), - new WeatherStation("Garissa", 29.3), - new WeatherStation("Garoua", 28.3), - new WeatherStation("George Town", 27.9), - new WeatherStation("Ghanzi", 21.4), - new WeatherStation("Gjoa Haven", -14.4), - new WeatherStation("Guadalajara", 20.9), - new WeatherStation("Guangzhou", 22.4), - new WeatherStation("Guatemala City", 20.4), - new WeatherStation("Halifax", 7.5), - new WeatherStation("Hamburg", 9.7), - new WeatherStation("Hamilton", 13.8), - new WeatherStation("Hanga Roa", 20.5), - new WeatherStation("Hanoi", 23.6), - new WeatherStation("Harare", 18.4), - new WeatherStation("Harbin", 5.0), - new WeatherStation("Hargeisa", 21.7), - new WeatherStation("Hat Yai", 27.0), - new WeatherStation("Havana", 25.2), - new WeatherStation("Helsinki", 5.9), - new WeatherStation("Heraklion", 18.9), - new WeatherStation("Hiroshima", 16.3), - new WeatherStation("Ho Chi Minh City", 27.4), - new WeatherStation("Hobart", 12.7), - new WeatherStation("Hong Kong", 23.3), - new WeatherStation("Honiara", 26.5), - new WeatherStation("Honolulu", 25.4), - new WeatherStation("Houston", 20.8), - new WeatherStation("Ifrane", 11.4), - new WeatherStation("Indianapolis", 11.8), - new WeatherStation("Iqaluit", -9.3), - new WeatherStation("Irkutsk", 1.0), - new WeatherStation("Istanbul", 13.9), - new WeatherStation("İzmir", 17.9), - new WeatherStation("Jacksonville", 20.3), - new WeatherStation("Jakarta", 26.7), - new WeatherStation("Jayapura", 27.0), - new WeatherStation("Jerusalem", 18.3), - new WeatherStation("Johannesburg", 15.5), - new WeatherStation("Jos", 22.8), - new WeatherStation("Juba", 27.8), - new WeatherStation("Kabul", 12.1), - new WeatherStation("Kampala", 20.0), - new WeatherStation("Kandi", 27.7), - new WeatherStation("Kankan", 26.5), - new WeatherStation("Kano", 26.4), - new WeatherStation("Kansas City", 12.5), - new WeatherStation("Karachi", 26.0), - new WeatherStation("Karonga", 24.4), - new WeatherStation("Kathmandu", 18.3), - new WeatherStation("Khartoum", 29.9), - new WeatherStation("Kingston", 27.4), - new WeatherStation("Kinshasa", 25.3), - new WeatherStation("Kolkata", 26.7), - new WeatherStation("Kuala Lumpur", 27.3), - new WeatherStation("Kumasi", 26.0), - new WeatherStation("Kunming", 15.7), - new WeatherStation("Kuopio", 3.4), - new WeatherStation("Kuwait City", 25.7), - new WeatherStation("Kyiv", 8.4), - new WeatherStation("Kyoto", 15.8), - new WeatherStation("La Ceiba", 26.2), - new WeatherStation("La Paz", 23.7), - new WeatherStation("Lagos", 26.8), - new WeatherStation("Lahore", 24.3), - new WeatherStation("Lake Havasu City", 23.7), - new WeatherStation("Lake Tekapo", 8.7), - new WeatherStation("Las Palmas de Gran Canaria", 21.2), - new WeatherStation("Las Vegas", 20.3), - new WeatherStation("Launceston", 13.1), - new WeatherStation("Lhasa", 7.6), - new WeatherStation("Libreville", 25.9), - new WeatherStation("Lisbon", 17.5), - new WeatherStation("Livingstone", 21.8), - new WeatherStation("Ljubljana", 10.9), - new WeatherStation("Lodwar", 29.3), - new WeatherStation("Lomé", 26.9), - new WeatherStation("London", 11.3), - new WeatherStation("Los Angeles", 18.6), - new WeatherStation("Louisville", 13.9), - new WeatherStation("Luanda", 25.8), - new WeatherStation("Lubumbashi", 20.8), - new WeatherStation("Lusaka", 19.9), - new WeatherStation("Luxembourg City", 9.3), - new WeatherStation("Lviv", 7.8), - new WeatherStation("Lyon", 12.5), - new WeatherStation("Madrid", 15.0), - new WeatherStation("Mahajanga", 26.3), - new WeatherStation("Makassar", 26.7), - new WeatherStation("Makurdi", 26.0), - new WeatherStation("Malabo", 26.3), - new WeatherStation("Malé", 28.0), - new WeatherStation("Managua", 27.3), - new WeatherStation("Manama", 26.5), - new WeatherStation("Mandalay", 28.0), - new WeatherStation("Mango", 28.1), - new WeatherStation("Manila", 28.4), - new WeatherStation("Maputo", 22.8), - new WeatherStation("Marrakesh", 19.6), - new WeatherStation("Marseille", 15.8), - new WeatherStation("Maun", 22.4), - new WeatherStation("Medan", 26.5), - new WeatherStation("Mek'ele", 22.7), - new WeatherStation("Melbourne", 15.1), - new WeatherStation("Memphis", 17.2), - new WeatherStation("Mexicali", 23.1), - new WeatherStation("Mexico City", 17.5), - new WeatherStation("Miami", 24.9), - new WeatherStation("Milan", 13.0), - new WeatherStation("Milwaukee", 8.9), - new WeatherStation("Minneapolis", 7.8), - new WeatherStation("Minsk", 6.7), - new WeatherStation("Mogadishu", 27.1), - new WeatherStation("Mombasa", 26.3), - new WeatherStation("Monaco", 16.4), - new WeatherStation("Moncton", 6.1), - new WeatherStation("Monterrey", 22.3), - new WeatherStation("Montreal", 6.8), - new WeatherStation("Moscow", 5.8), - new WeatherStation("Mumbai", 27.1), - new WeatherStation("Murmansk", 0.6), - new WeatherStation("Muscat", 28.0), - new WeatherStation("Mzuzu", 17.7), - new WeatherStation("N'Djamena", 28.3), - new WeatherStation("Naha", 23.1), - new WeatherStation("Nairobi", 17.8), - new WeatherStation("Nakhon Ratchasima", 27.3), - new WeatherStation("Napier", 14.6), - new WeatherStation("Napoli", 15.9), - new WeatherStation("Nashville", 15.4), - new WeatherStation("Nassau", 24.6), - new WeatherStation("Ndola", 20.3), - new WeatherStation("New Delhi", 25.0), - new WeatherStation("New Orleans", 20.7), - new WeatherStation("New York City", 12.9), - new WeatherStation("Ngaoundéré", 22.0), - new WeatherStation("Niamey", 29.3), - new WeatherStation("Nicosia", 19.7), - new WeatherStation("Niigata", 13.9), - new WeatherStation("Nouadhibou", 21.3), - new WeatherStation("Nouakchott", 25.7), - new WeatherStation("Novosibirsk", 1.7), - new WeatherStation("Nuuk", -1.4), - new WeatherStation("Odesa", 10.7), - new WeatherStation("Odienné", 26.0), - new WeatherStation("Oklahoma City", 15.9), - new WeatherStation("Omaha", 10.6), - new WeatherStation("Oranjestad", 28.1), - new WeatherStation("Oslo", 5.7), - new WeatherStation("Ottawa", 6.6), - new WeatherStation("Ouagadougou", 28.3), - new WeatherStation("Ouahigouya", 28.6), - new WeatherStation("Ouarzazate", 18.9), - new WeatherStation("Oulu", 2.7), - new WeatherStation("Palembang", 27.3), - new WeatherStation("Palermo", 18.5), - new WeatherStation("Palm Springs", 24.5), - new WeatherStation("Palmerston North", 13.2), - new WeatherStation("Panama City", 28.0), - new WeatherStation("Parakou", 26.8), - new WeatherStation("Paris", 12.3), - new WeatherStation("Perth", 18.7), - new WeatherStation("Petropavlovsk-Kamchatsky", 1.9), - new WeatherStation("Philadelphia", 13.2), - new WeatherStation("Phnom Penh", 28.3), - new WeatherStation("Phoenix", 23.9), - new WeatherStation("Pittsburgh", 10.8), - new WeatherStation("Podgorica", 15.3), - new WeatherStation("Pointe-Noire", 26.1), - new WeatherStation("Pontianak", 27.7), - new WeatherStation("Port Moresby", 26.9), - new WeatherStation("Port Sudan", 28.4), - new WeatherStation("Port Vila", 24.3), - new WeatherStation("Port-Gentil", 26.0), - new WeatherStation("Portland (OR)", 12.4), - new WeatherStation("Porto", 15.7), - new WeatherStation("Prague", 8.4), - new WeatherStation("Praia", 24.4), - new WeatherStation("Pretoria", 18.2), - new WeatherStation("Pyongyang", 10.8), - new WeatherStation("Rabat", 17.2), - new WeatherStation("Rangpur", 24.4), - new WeatherStation("Reggane", 28.3), - new WeatherStation("Reykjavík", 4.3), - new WeatherStation("Riga", 6.2), - new WeatherStation("Riyadh", 26.0), - new WeatherStation("Rome", 15.2), - new WeatherStation("Roseau", 26.2), - new WeatherStation("Rostov-on-Don", 9.9), - new WeatherStation("Sacramento", 16.3), - new WeatherStation("Saint Petersburg", 5.8), - new WeatherStation("Saint-Pierre", 5.7), - new WeatherStation("Salt Lake City", 11.6), - new WeatherStation("San Antonio", 20.8), - new WeatherStation("San Diego", 17.8), - new WeatherStation("San Francisco", 14.6), - new WeatherStation("San Jose", 16.4), - new WeatherStation("San José", 22.6), - new WeatherStation("San Juan", 27.2), - new WeatherStation("San Salvador", 23.1), - new WeatherStation("Sana'a", 20.0), - new WeatherStation("Santo Domingo", 25.9), - new WeatherStation("Sapporo", 8.9), - new WeatherStation("Sarajevo", 10.1), - new WeatherStation("Saskatoon", 3.3), - new WeatherStation("Seattle", 11.3), - new WeatherStation("Ségou", 28.0), - new WeatherStation("Seoul", 12.5), - new WeatherStation("Seville", 19.2), - new WeatherStation("Shanghai", 16.7), - new WeatherStation("Singapore", 27.0), - new WeatherStation("Skopje", 12.4), - new WeatherStation("Sochi", 14.2), - new WeatherStation("Sofia", 10.6), - new WeatherStation("Sokoto", 28.0), - new WeatherStation("Split", 16.1), - new WeatherStation("St. John's", 5.0), - new WeatherStation("St. Louis", 13.9), - new WeatherStation("Stockholm", 6.6), - new WeatherStation("Surabaya", 27.1), - new WeatherStation("Suva", 25.6), - new WeatherStation("Suwałki", 7.2), - new WeatherStation("Sydney", 17.7), - new WeatherStation("Tabora", 23.0), - new WeatherStation("Tabriz", 12.6), - new WeatherStation("Taipei", 23.0), - new WeatherStation("Tallinn", 6.4), - new WeatherStation("Tamale", 27.9), - new WeatherStation("Tamanrasset", 21.7), - new WeatherStation("Tampa", 22.9), - new WeatherStation("Tashkent", 14.8), - new WeatherStation("Tauranga", 14.8), - new WeatherStation("Tbilisi", 12.9), - new WeatherStation("Tegucigalpa", 21.7), - new WeatherStation("Tehran", 17.0), - new WeatherStation("Tel Aviv", 20.0), - new WeatherStation("Thessaloniki", 16.0), - new WeatherStation("Thiès", 24.0), - new WeatherStation("Tijuana", 17.8), - new WeatherStation("Timbuktu", 28.0), - new WeatherStation("Tirana", 15.2), - new WeatherStation("Toamasina", 23.4), - new WeatherStation("Tokyo", 15.4), - new WeatherStation("Toliara", 24.1), - new WeatherStation("Toluca", 12.4), - new WeatherStation("Toronto", 9.4), - new WeatherStation("Tripoli", 20.0), - new WeatherStation("Tromsø", 2.9), - new WeatherStation("Tucson", 20.9), - new WeatherStation("Tunis", 18.4), - new WeatherStation("Ulaanbaatar", -0.4), - new WeatherStation("Upington", 20.4), - new WeatherStation("Ürümqi", 7.4), - new WeatherStation("Vaduz", 10.1), - new WeatherStation("Valencia", 18.3), - new WeatherStation("Valletta", 18.8), - new WeatherStation("Vancouver", 10.4), - new WeatherStation("Veracruz", 25.4), - new WeatherStation("Vienna", 10.4), - new WeatherStation("Vientiane", 25.9), - new WeatherStation("Villahermosa", 27.1), - new WeatherStation("Vilnius", 6.0), - new WeatherStation("Virginia Beach", 15.8), - new WeatherStation("Vladivostok", 4.9), - new WeatherStation("Warsaw", 8.5), - new WeatherStation("Washington, D.C.", 14.6), - new WeatherStation("Wau", 27.8), - new WeatherStation("Wellington", 12.9), - new WeatherStation("Whitehorse", -0.1), - new WeatherStation("Wichita", 13.9), - new WeatherStation("Willemstad", 28.0), - new WeatherStation("Winnipeg", 3.0), - new WeatherStation("Wrocław", 9.6), - new WeatherStation("Xi'an", 14.1), - new WeatherStation("Yakutsk", -8.8), - new WeatherStation("Yangon", 27.5), - new WeatherStation("Yaoundé", 23.8), - new WeatherStation("Yellowknife", -4.3), - new WeatherStation("Yerevan", 12.4), - new WeatherStation("Yinchuan", 9.0), - new WeatherStation("Zagreb", 10.7), - new WeatherStation("Zanzibar City", 26.0), - new WeatherStation("Zürich", 9.3)); + final List stations = WeatherStation.getRandomWeatherStationsList(); File file = new File(FILE); diff --git a/src/main/java/dev/morling/onebrc/WeatherStation.java b/src/main/java/dev/morling/onebrc/WeatherStation.java new file mode 100644 index 000000000..b5fb7c589 --- /dev/null +++ b/src/main/java/dev/morling/onebrc/WeatherStation.java @@ -0,0 +1,69 @@ +/* + * 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 org.rschwietzke.FastRandom; +import org.rschwietzke.CheaperCharBuffer; + +public class WeatherStation { + final static char[] NUMBERS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; + + public final String id; + public final double meanTemperature; + + private final char[] firstPart; + private final Random random; + private final FastRandom fastRandom; + + public WeatherStation(long seed, String id, double meanTemperature) { + this.id = id; + this.meanTemperature = meanTemperature; + + long rngSeed = ((long) id.hashCode()) ^ seed; + + this.random = new Random(rngSeed); + this.fastRandom = new FastRandom(rngSeed); + + this.firstPart = (id + ";").toCharArray(); + } + + public double measurement() { + double m = this.random.nextGaussian(this.meanTemperature, 10); + return Math.round(m * 10.0) / 10.0; + } + + /** + * We write out data into the buffer to avoid string conversion + * We also no longer use double and gaussian, because for our + * purpose, the fake numbers here will do it. Less + * + * @param buffer the buffer to append to + */ + public void measurement(final CheaperCharBuffer buffer) { + + // fake -10.9 to +10.9 variance without double operations and rounding + // gives us -10 to +10 + int m = (int) meanTemperature + (this.fastRandom.nextInt(21) - 10); + // gives us a decimal digit 0 to 9 as char + char d = NUMBERS[this.fastRandom.nextInt(10)]; + + // just append, only one number has to be converted and we can do + // better... if we watn + buffer.append(firstPart, 0, firstPart.length) + .append(String.valueOf(m)).append('.').append(d) + .append('\n'); + } +} \ No newline at end of file diff --git a/src/main/java/dev/morling/onebrc/WeatherStationFactory.java b/src/main/java/dev/morling/onebrc/WeatherStationFactory.java new file mode 100644 index 000000000..a49938106 --- /dev/null +++ b/src/main/java/dev/morling/onebrc/WeatherStationFactory.java @@ -0,0 +1,472 @@ +/* + * 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 java.util.Arrays; +import java.util.Random; +import java.util.List; + +import org.rschwietzke.CheaperCharBuffer; +import org.rschwietzke.FastRandom; + +public class WeatherStationFactory { + + public static List getRandomWeatherStationsList() { + return WeatherStationFactory.getWeatherStationsList(java.util.concurrent.ThreadLocalRandom.current().nextLong()); + } + + public static List getWeatherStationsList(long seed) { + // @formatter:off + // data from https://en.wikipedia.org/wiki/List_of_cities_by_average_temperature; + // converted using https://wikitable2csv.ggor.de/ + // brought to form using DuckDB: + // D copy ( + // select City, regexp_extract(Year,'(.*)\n.*', 1) as AverageTemp + // from ( + // select City,Year + // from read_csv_auto('List_of_cities_by_average_temperature_1.csv', header = true) + // union + // select City,Year + // from read_csv_auto('List_of_cities_by_average_temperature_2.csv', header = true) + // union + // select City,Year + // from read_csv_auto('List_of_cities_by_average_temperature_3.csv', header = true) + // union + // select City,Year + // from read_csv_auto('List_of_cities_by_average_temperature_4.csv', header = true) + // union + // select City,Year + // from read_csv_auto('List_of_cities_by_average_temperature_5.csv', header = true) + // ) + // ) TO 'output.csv' (HEADER, DELIMITER ','); + // @formatter:on + return Arrays.asList( + new WeatherStation(seed, "Abha", 18.0), + new WeatherStation(seed, "Abidjan", 26.0), + new WeatherStation(seed, "Abéché", 29.4), + new WeatherStation(seed, "Accra", 26.4), + new WeatherStation(seed, "Addis Ababa", 16.0), + new WeatherStation(seed, "Adelaide", 17.3), + new WeatherStation(seed, "Aden", 29.1), + new WeatherStation(seed, "Ahvaz", 25.4), + new WeatherStation(seed, "Albuquerque", 14.0), + new WeatherStation(seed, "Alexandra", 11.0), + new WeatherStation(seed, "Alexandria", 20.0), + new WeatherStation(seed, "Algiers", 18.2), + new WeatherStation(seed, "Alice Springs", 21.0), + new WeatherStation(seed, "Almaty", 10.0), + new WeatherStation(seed, "Amsterdam", 10.2), + new WeatherStation(seed, "Anadyr", -6.9), + new WeatherStation(seed, "Anchorage", 2.8), + new WeatherStation(seed, "Andorra la Vella", 9.8), + new WeatherStation(seed, "Ankara", 12.0), + new WeatherStation(seed, "Antananarivo", 17.9), + new WeatherStation(seed, "Antsiranana", 25.2), + new WeatherStation(seed, "Arkhangelsk", 1.3), + new WeatherStation(seed, "Ashgabat", 17.1), + new WeatherStation(seed, "Asmara", 15.6), + new WeatherStation(seed, "Assab", 30.5), + new WeatherStation(seed, "Astana", 3.5), + new WeatherStation(seed, "Athens", 19.2), + new WeatherStation(seed, "Atlanta", 17.0), + new WeatherStation(seed, "Auckland", 15.2), + new WeatherStation(seed, "Austin", 20.7), + new WeatherStation(seed, "Baghdad", 22.77), + new WeatherStation(seed, "Baguio", 19.5), + new WeatherStation(seed, "Baku", 15.1), + new WeatherStation(seed, "Baltimore", 13.1), + new WeatherStation(seed, "Bamako", 27.8), + new WeatherStation(seed, "Bangkok", 28.6), + new WeatherStation(seed, "Bangui", 26.0), + new WeatherStation(seed, "Banjul", 26.0), + new WeatherStation(seed, "Barcelona", 18.2), + new WeatherStation(seed, "Bata", 25.1), + new WeatherStation(seed, "Batumi", 14.0), + new WeatherStation(seed, "Beijing", 12.9), + new WeatherStation(seed, "Beirut", 20.9), + new WeatherStation(seed, "Belgrade", 12.5), + new WeatherStation(seed, "Belize City", 26.7), + new WeatherStation(seed, "Benghazi", 19.9), + new WeatherStation(seed, "Bergen", 7.7), + new WeatherStation(seed, "Berlin", 10.3), + new WeatherStation(seed, "Bilbao", 14.7), + new WeatherStation(seed, "Birao", 26.5), + new WeatherStation(seed, "Bishkek", 11.3), + new WeatherStation(seed, "Bissau", 27.0), + new WeatherStation(seed, "Blantyre", 22.2), + new WeatherStation(seed, "Bloemfontein", 15.6), + new WeatherStation(seed, "Boise", 11.4), + new WeatherStation(seed, "Bordeaux", 14.2), + new WeatherStation(seed, "Bosaso", 30.0), + new WeatherStation(seed, "Boston", 10.9), + new WeatherStation(seed, "Bouaké", 26.0), + new WeatherStation(seed, "Bratislava", 10.5), + new WeatherStation(seed, "Brazzaville", 25.0), + new WeatherStation(seed, "Bridgetown", 27.0), + new WeatherStation(seed, "Brisbane", 21.4), + new WeatherStation(seed, "Brussels", 10.5), + new WeatherStation(seed, "Bucharest", 10.8), + new WeatherStation(seed, "Budapest", 11.3), + new WeatherStation(seed, "Bujumbura", 23.8), + new WeatherStation(seed, "Bulawayo", 18.9), + new WeatherStation(seed, "Burnie", 13.1), + new WeatherStation(seed, "Busan", 15.0), + new WeatherStation(seed, "Cabo San Lucas", 23.9), + new WeatherStation(seed, "Cairns", 25.0), + new WeatherStation(seed, "Cairo", 21.4), + new WeatherStation(seed, "Calgary", 4.4), + new WeatherStation(seed, "Canberra", 13.1), + new WeatherStation(seed, "Cape Town", 16.2), + new WeatherStation(seed, "Changsha", 17.4), + new WeatherStation(seed, "Charlotte", 16.1), + new WeatherStation(seed, "Chiang Mai", 25.8), + new WeatherStation(seed, "Chicago", 9.8), + new WeatherStation(seed, "Chihuahua", 18.6), + new WeatherStation(seed, "Chișinău", 10.2), + new WeatherStation(seed, "Chittagong", 25.9), + new WeatherStation(seed, "Chongqing", 18.6), + new WeatherStation(seed, "Christchurch", 12.2), + new WeatherStation(seed, "City of San Marino", 11.8), + new WeatherStation(seed, "Colombo", 27.4), + new WeatherStation(seed, "Columbus", 11.7), + new WeatherStation(seed, "Conakry", 26.4), + new WeatherStation(seed, "Copenhagen", 9.1), + new WeatherStation(seed, "Cotonou", 27.2), + new WeatherStation(seed, "Cracow", 9.3), + new WeatherStation(seed, "Da Lat", 17.9), + new WeatherStation(seed, "Da Nang", 25.8), + new WeatherStation(seed, "Dakar", 24.0), + new WeatherStation(seed, "Dallas", 19.0), + new WeatherStation(seed, "Damascus", 17.0), + new WeatherStation(seed, "Dampier", 26.4), + new WeatherStation(seed, "Dar es Salaam", 25.8), + new WeatherStation(seed, "Darwin", 27.6), + new WeatherStation(seed, "Denpasar", 23.7), + new WeatherStation(seed, "Denver", 10.4), + new WeatherStation(seed, "Detroit", 10.0), + new WeatherStation(seed, "Dhaka", 25.9), + new WeatherStation(seed, "Dikson", -11.1), + new WeatherStation(seed, "Dili", 26.6), + new WeatherStation(seed, "Djibouti", 29.9), + new WeatherStation(seed, "Dodoma", 22.7), + new WeatherStation(seed, "Dolisie", 24.0), + new WeatherStation(seed, "Douala", 26.7), + new WeatherStation(seed, "Dubai", 26.9), + new WeatherStation(seed, "Dublin", 9.8), + new WeatherStation(seed, "Dunedin", 11.1), + new WeatherStation(seed, "Durban", 20.6), + new WeatherStation(seed, "Dushanbe", 14.7), + new WeatherStation(seed, "Edinburgh", 9.3), + new WeatherStation(seed, "Edmonton", 4.2), + new WeatherStation(seed, "El Paso", 18.1), + new WeatherStation(seed, "Entebbe", 21.0), + new WeatherStation(seed, "Erbil", 19.5), + new WeatherStation(seed, "Erzurum", 5.1), + new WeatherStation(seed, "Fairbanks", -2.3), + new WeatherStation(seed, "Fianarantsoa", 17.9), + new WeatherStation(seed, "Flores, Petén", 26.4), + new WeatherStation(seed, "Frankfurt", 10.6), + new WeatherStation(seed, "Fresno", 17.9), + new WeatherStation(seed, "Fukuoka", 17.0), + new WeatherStation(seed, "Gabès", 19.5), + new WeatherStation(seed, "Gaborone", 21.0), + new WeatherStation(seed, "Gagnoa", 26.0), + new WeatherStation(seed, "Gangtok", 15.2), + new WeatherStation(seed, "Garissa", 29.3), + new WeatherStation(seed, "Garoua", 28.3), + new WeatherStation(seed, "George Town", 27.9), + new WeatherStation(seed, "Ghanzi", 21.4), + new WeatherStation(seed, "Gjoa Haven", -14.4), + new WeatherStation(seed, "Guadalajara", 20.9), + new WeatherStation(seed, "Guangzhou", 22.4), + new WeatherStation(seed, "Guatemala City", 20.4), + new WeatherStation(seed, "Halifax", 7.5), + new WeatherStation(seed, "Hamburg", 9.7), + new WeatherStation(seed, "Hamilton", 13.8), + new WeatherStation(seed, "Hanga Roa", 20.5), + new WeatherStation(seed, "Hanoi", 23.6), + new WeatherStation(seed, "Harare", 18.4), + new WeatherStation(seed, "Harbin", 5.0), + new WeatherStation(seed, "Hargeisa", 21.7), + new WeatherStation(seed, "Hat Yai", 27.0), + new WeatherStation(seed, "Havana", 25.2), + new WeatherStation(seed, "Helsinki", 5.9), + new WeatherStation(seed, "Heraklion", 18.9), + new WeatherStation(seed, "Hiroshima", 16.3), + new WeatherStation(seed, "Ho Chi Minh City", 27.4), + new WeatherStation(seed, "Hobart", 12.7), + new WeatherStation(seed, "Hong Kong", 23.3), + new WeatherStation(seed, "Honiara", 26.5), + new WeatherStation(seed, "Honolulu", 25.4), + new WeatherStation(seed, "Houston", 20.8), + new WeatherStation(seed, "Ifrane", 11.4), + new WeatherStation(seed, "Indianapolis", 11.8), + new WeatherStation(seed, "Iqaluit", -9.3), + new WeatherStation(seed, "Irkutsk", 1.0), + new WeatherStation(seed, "Istanbul", 13.9), + new WeatherStation(seed, "İzmir", 17.9), + new WeatherStation(seed, "Jacksonville", 20.3), + new WeatherStation(seed, "Jakarta", 26.7), + new WeatherStation(seed, "Jayapura", 27.0), + new WeatherStation(seed, "Jerusalem", 18.3), + new WeatherStation(seed, "Johannesburg", 15.5), + new WeatherStation(seed, "Jos", 22.8), + new WeatherStation(seed, "Juba", 27.8), + new WeatherStation(seed, "Kabul", 12.1), + new WeatherStation(seed, "Kampala", 20.0), + new WeatherStation(seed, "Kandi", 27.7), + new WeatherStation(seed, "Kankan", 26.5), + new WeatherStation(seed, "Kano", 26.4), + new WeatherStation(seed, "Kansas City", 12.5), + new WeatherStation(seed, "Karachi", 26.0), + new WeatherStation(seed, "Karonga", 24.4), + new WeatherStation(seed, "Kathmandu", 18.3), + new WeatherStation(seed, "Khartoum", 29.9), + new WeatherStation(seed, "Kingston", 27.4), + new WeatherStation(seed, "Kinshasa", 25.3), + new WeatherStation(seed, "Kolkata", 26.7), + new WeatherStation(seed, "Kuala Lumpur", 27.3), + new WeatherStation(seed, "Kumasi", 26.0), + new WeatherStation(seed, "Kunming", 15.7), + new WeatherStation(seed, "Kuopio", 3.4), + new WeatherStation(seed, "Kuwait City", 25.7), + new WeatherStation(seed, "Kyiv", 8.4), + new WeatherStation(seed, "Kyoto", 15.8), + new WeatherStation(seed, "La Ceiba", 26.2), + new WeatherStation(seed, "La Paz", 23.7), + new WeatherStation(seed, "Lagos", 26.8), + new WeatherStation(seed, "Lahore", 24.3), + new WeatherStation(seed, "Lake Havasu City", 23.7), + new WeatherStation(seed, "Lake Tekapo", 8.7), + new WeatherStation(seed, "Las Palmas de Gran Canaria", 21.2), + new WeatherStation(seed, "Las Vegas", 20.3), + new WeatherStation(seed, "Launceston", 13.1), + new WeatherStation(seed, "Lhasa", 7.6), + new WeatherStation(seed, "Libreville", 25.9), + new WeatherStation(seed, "Lisbon", 17.5), + new WeatherStation(seed, "Livingstone", 21.8), + new WeatherStation(seed, "Ljubljana", 10.9), + new WeatherStation(seed, "Lodwar", 29.3), + new WeatherStation(seed, "Lomé", 26.9), + new WeatherStation(seed, "London", 11.3), + new WeatherStation(seed, "Los Angeles", 18.6), + new WeatherStation(seed, "Louisville", 13.9), + new WeatherStation(seed, "Luanda", 25.8), + new WeatherStation(seed, "Lubumbashi", 20.8), + new WeatherStation(seed, "Lusaka", 19.9), + new WeatherStation(seed, "Luxembourg City", 9.3), + new WeatherStation(seed, "Lviv", 7.8), + new WeatherStation(seed, "Lyon", 12.5), + new WeatherStation(seed, "Madrid", 15.0), + new WeatherStation(seed, "Mahajanga", 26.3), + new WeatherStation(seed, "Makassar", 26.7), + new WeatherStation(seed, "Makurdi", 26.0), + new WeatherStation(seed, "Malabo", 26.3), + new WeatherStation(seed, "Malé", 28.0), + new WeatherStation(seed, "Managua", 27.3), + new WeatherStation(seed, "Manama", 26.5), + new WeatherStation(seed, "Mandalay", 28.0), + new WeatherStation(seed, "Mango", 28.1), + new WeatherStation(seed, "Manila", 28.4), + new WeatherStation(seed, "Maputo", 22.8), + new WeatherStation(seed, "Marrakesh", 19.6), + new WeatherStation(seed, "Marseille", 15.8), + new WeatherStation(seed, "Maun", 22.4), + new WeatherStation(seed, "Medan", 26.5), + new WeatherStation(seed, "Mek'ele", 22.7), + new WeatherStation(seed, "Melbourne", 15.1), + new WeatherStation(seed, "Memphis", 17.2), + new WeatherStation(seed, "Mexicali", 23.1), + new WeatherStation(seed, "Mexico City", 17.5), + new WeatherStation(seed, "Miami", 24.9), + new WeatherStation(seed, "Milan", 13.0), + new WeatherStation(seed, "Milwaukee", 8.9), + new WeatherStation(seed, "Minneapolis", 7.8), + new WeatherStation(seed, "Minsk", 6.7), + new WeatherStation(seed, "Mogadishu", 27.1), + new WeatherStation(seed, "Mombasa", 26.3), + new WeatherStation(seed, "Monaco", 16.4), + new WeatherStation(seed, "Moncton", 6.1), + new WeatherStation(seed, "Monterrey", 22.3), + new WeatherStation(seed, "Montreal", 6.8), + new WeatherStation(seed, "Moscow", 5.8), + new WeatherStation(seed, "Mumbai", 27.1), + new WeatherStation(seed, "Murmansk", 0.6), + new WeatherStation(seed, "Muscat", 28.0), + new WeatherStation(seed, "Mzuzu", 17.7), + new WeatherStation(seed, "N'Djamena", 28.3), + new WeatherStation(seed, "Naha", 23.1), + new WeatherStation(seed, "Nairobi", 17.8), + new WeatherStation(seed, "Nakhon Ratchasima", 27.3), + new WeatherStation(seed, "Napier", 14.6), + new WeatherStation(seed, "Napoli", 15.9), + new WeatherStation(seed, "Nashville", 15.4), + new WeatherStation(seed, "Nassau", 24.6), + new WeatherStation(seed, "Ndola", 20.3), + new WeatherStation(seed, "New Delhi", 25.0), + new WeatherStation(seed, "New Orleans", 20.7), + new WeatherStation(seed, "New York City", 12.9), + new WeatherStation(seed, "Ngaoundéré", 22.0), + new WeatherStation(seed, "Niamey", 29.3), + new WeatherStation(seed, "Nicosia", 19.7), + new WeatherStation(seed, "Niigata", 13.9), + new WeatherStation(seed, "Nouadhibou", 21.3), + new WeatherStation(seed, "Nouakchott", 25.7), + new WeatherStation(seed, "Novosibirsk", 1.7), + new WeatherStation(seed, "Nuuk", -1.4), + new WeatherStation(seed, "Odesa", 10.7), + new WeatherStation(seed, "Odienné", 26.0), + new WeatherStation(seed, "Oklahoma City", 15.9), + new WeatherStation(seed, "Omaha", 10.6), + new WeatherStation(seed, "Oranjestad", 28.1), + new WeatherStation(seed, "Oslo", 5.7), + new WeatherStation(seed, "Ottawa", 6.6), + new WeatherStation(seed, "Ouagadougou", 28.3), + new WeatherStation(seed, "Ouahigouya", 28.6), + new WeatherStation(seed, "Ouarzazate", 18.9), + new WeatherStation(seed, "Oulu", 2.7), + new WeatherStation(seed, "Palembang", 27.3), + new WeatherStation(seed, "Palermo", 18.5), + new WeatherStation(seed, "Palm Springs", 24.5), + new WeatherStation(seed, "Palmerston North", 13.2), + new WeatherStation(seed, "Panama City", 28.0), + new WeatherStation(seed, "Parakou", 26.8), + new WeatherStation(seed, "Paris", 12.3), + new WeatherStation(seed, "Perth", 18.7), + new WeatherStation(seed, "Petropavlovsk-Kamchatsky", 1.9), + new WeatherStation(seed, "Philadelphia", 13.2), + new WeatherStation(seed, "Phnom Penh", 28.3), + new WeatherStation(seed, "Phoenix", 23.9), + new WeatherStation(seed, "Pittsburgh", 10.8), + new WeatherStation(seed, "Podgorica", 15.3), + new WeatherStation(seed, "Pointe-Noire", 26.1), + new WeatherStation(seed, "Pontianak", 27.7), + new WeatherStation(seed, "Port Moresby", 26.9), + new WeatherStation(seed, "Port Sudan", 28.4), + new WeatherStation(seed, "Port Vila", 24.3), + new WeatherStation(seed, "Port-Gentil", 26.0), + new WeatherStation(seed, "Portland (OR)", 12.4), + new WeatherStation(seed, "Porto", 15.7), + new WeatherStation(seed, "Prague", 8.4), + new WeatherStation(seed, "Praia", 24.4), + new WeatherStation(seed, "Pretoria", 18.2), + new WeatherStation(seed, "Pyongyang", 10.8), + new WeatherStation(seed, "Rabat", 17.2), + new WeatherStation(seed, "Rangpur", 24.4), + new WeatherStation(seed, "Reggane", 28.3), + new WeatherStation(seed, "Reykjavík", 4.3), + new WeatherStation(seed, "Riga", 6.2), + new WeatherStation(seed, "Riyadh", 26.0), + new WeatherStation(seed, "Rome", 15.2), + new WeatherStation(seed, "Roseau", 26.2), + new WeatherStation(seed, "Rostov-on-Don", 9.9), + new WeatherStation(seed, "Sacramento", 16.3), + new WeatherStation(seed, "Saint Petersburg", 5.8), + new WeatherStation(seed, "Saint-Pierre", 5.7), + new WeatherStation(seed, "Salt Lake City", 11.6), + new WeatherStation(seed, "San Antonio", 20.8), + new WeatherStation(seed, "San Diego", 17.8), + new WeatherStation(seed, "San Francisco", 14.6), + new WeatherStation(seed, "San Jose", 16.4), + new WeatherStation(seed, "San José", 22.6), + new WeatherStation(seed, "San Juan", 27.2), + new WeatherStation(seed, "San Salvador", 23.1), + new WeatherStation(seed, "Sana'a", 20.0), + new WeatherStation(seed, "Santo Domingo", 25.9), + new WeatherStation(seed, "Sapporo", 8.9), + new WeatherStation(seed, "Sarajevo", 10.1), + new WeatherStation(seed, "Saskatoon", 3.3), + new WeatherStation(seed, "Seattle", 11.3), + new WeatherStation(seed, "Ségou", 28.0), + new WeatherStation(seed, "Seoul", 12.5), + new WeatherStation(seed, "Seville", 19.2), + new WeatherStation(seed, "Shanghai", 16.7), + new WeatherStation(seed, "Singapore", 27.0), + new WeatherStation(seed, "Skopje", 12.4), + new WeatherStation(seed, "Sochi", 14.2), + new WeatherStation(seed, "Sofia", 10.6), + new WeatherStation(seed, "Sokoto", 28.0), + new WeatherStation(seed, "Split", 16.1), + new WeatherStation(seed, "St. John's", 5.0), + new WeatherStation(seed, "St. Louis", 13.9), + new WeatherStation(seed, "Stockholm", 6.6), + new WeatherStation(seed, "Surabaya", 27.1), + new WeatherStation(seed, "Suva", 25.6), + new WeatherStation(seed, "Suwałki", 7.2), + new WeatherStation(seed, "Sydney", 17.7), + new WeatherStation(seed, "Tabora", 23.0), + new WeatherStation(seed, "Tabriz", 12.6), + new WeatherStation(seed, "Taipei", 23.0), + new WeatherStation(seed, "Tallinn", 6.4), + new WeatherStation(seed, "Tamale", 27.9), + new WeatherStation(seed, "Tamanrasset", 21.7), + new WeatherStation(seed, "Tampa", 22.9), + new WeatherStation(seed, "Tashkent", 14.8), + new WeatherStation(seed, "Tauranga", 14.8), + new WeatherStation(seed, "Tbilisi", 12.9), + new WeatherStation(seed, "Tegucigalpa", 21.7), + new WeatherStation(seed, "Tehran", 17.0), + new WeatherStation(seed, "Tel Aviv", 20.0), + new WeatherStation(seed, "Thessaloniki", 16.0), + new WeatherStation(seed, "Thiès", 24.0), + new WeatherStation(seed, "Tijuana", 17.8), + new WeatherStation(seed, "Timbuktu", 28.0), + new WeatherStation(seed, "Tirana", 15.2), + new WeatherStation(seed, "Toamasina", 23.4), + new WeatherStation(seed, "Tokyo", 15.4), + new WeatherStation(seed, "Toliara", 24.1), + new WeatherStation(seed, "Toluca", 12.4), + new WeatherStation(seed, "Toronto", 9.4), + new WeatherStation(seed, "Tripoli", 20.0), + new WeatherStation(seed, "Tromsø", 2.9), + new WeatherStation(seed, "Tucson", 20.9), + new WeatherStation(seed, "Tunis", 18.4), + new WeatherStation(seed, "Ulaanbaatar", -0.4), + new WeatherStation(seed, "Upington", 20.4), + new WeatherStation(seed, "Ürümqi", 7.4), + new WeatherStation(seed, "Vaduz", 10.1), + new WeatherStation(seed, "Valencia", 18.3), + new WeatherStation(seed, "Valletta", 18.8), + new WeatherStation(seed, "Vancouver", 10.4), + new WeatherStation(seed, "Veracruz", 25.4), + new WeatherStation(seed, "Vienna", 10.4), + new WeatherStation(seed, "Vientiane", 25.9), + new WeatherStation(seed, "Villahermosa", 27.1), + new WeatherStation(seed, "Vilnius", 6.0), + new WeatherStation(seed, "Virginia Beach", 15.8), + new WeatherStation(seed, "Vladivostok", 4.9), + new WeatherStation(seed, "Warsaw", 8.5), + new WeatherStation(seed, "Washington, D.C.", 14.6), + new WeatherStation(seed, "Wau", 27.8), + new WeatherStation(seed, "Wellington", 12.9), + new WeatherStation(seed, "Whitehorse", -0.1), + new WeatherStation(seed, "Wichita", 13.9), + new WeatherStation(seed, "Willemstad", 28.0), + new WeatherStation(seed, "Winnipeg", 3.0), + new WeatherStation(seed, "Wrocław", 9.6), + new WeatherStation(seed, "Xi'an", 14.1), + new WeatherStation(seed, "Yakutsk", -8.8), + new WeatherStation(seed, "Yangon", 27.5), + new WeatherStation(seed, "Yaoundé", 23.8), + new WeatherStation(seed, "Yellowknife", -4.3), + new WeatherStation(seed, "Yerevan", 12.4), + new WeatherStation(seed, "Yinchuan", 9.0), + new WeatherStation(seed, "Zagreb", 10.7), + new WeatherStation(seed, "Zanzibar City", 26.0), + new WeatherStation(seed, "Zürich", 9.3)); + } +} \ No newline at end of file From aaf43a116af94979c5f11fe026c89a9a8d7d7e2d Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Fri, 5 Jan 2024 18:57:33 +0000 Subject: [PATCH 4/8] Use FastRandom for everything and make CreateMeasurements and CreateMeasurements2 produce the same output --- create_measurements2.sh | 2 +- .../morling/onebrc/CreateMeasurements.java | 4 +- .../morling/onebrc/CreateMeasurements2.java | 79 +++++++++++++------ .../dev/morling/onebrc/WeatherStation.java | 40 ++++++---- 4 files changed, 83 insertions(+), 42 deletions(-) diff --git a/create_measurements2.sh b/create_measurements2.sh index d262e4439..157dbf12d 100755 --- a/create_measurements2.sh +++ b/create_measurements2.sh @@ -16,4 +16,4 @@ # -java --class-path target/average-1.0.0-SNAPSHOT.jar dev.morling.onebrc.CreateMeasurements2 $1 +java --class-path target/average-1.0.0-SNAPSHOT.jar dev.morling.onebrc.CreateMeasurements2 $1 $2 diff --git a/src/main/java/dev/morling/onebrc/CreateMeasurements.java b/src/main/java/dev/morling/onebrc/CreateMeasurements.java index 68575ab53..59e51f0f5 100644 --- a/src/main/java/dev/morling/onebrc/CreateMeasurements.java +++ b/src/main/java/dev/morling/onebrc/CreateMeasurements.java @@ -23,6 +23,8 @@ import java.util.concurrent.ThreadLocalRandom; import java.util.Random; +import org.rschwietzke.FastRandom; + public class CreateMeasurements { private static final Path MEASUREMENT_FILE = Path.of("./measurements.txt"); @@ -60,7 +62,7 @@ public static void main(String[] args) throws Exception { List stations = WeatherStationFactory.getWeatherStationsList(seed); - Random random = new Random(seed); + FastRandom random = new FastRandom(seed); try (BufferedWriter bw = Files.newBufferedWriter(MEASUREMENT_FILE)) { for (int i = 0; i < size; i++) { if (i > 0 && i % 50_000_000 == 0) { diff --git a/src/main/java/dev/morling/onebrc/CreateMeasurements2.java b/src/main/java/dev/morling/onebrc/CreateMeasurements2.java index e9898f1b2..06b01dea8 100644 --- a/src/main/java/dev/morling/onebrc/CreateMeasurements2.java +++ b/src/main/java/dev/morling/onebrc/CreateMeasurements2.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.util.Arrays; import java.util.List; +import java.util.Random; import java.util.concurrent.ThreadLocalRandom; import org.rschwietzke.CheaperCharBuffer; @@ -37,8 +38,8 @@ public class CreateMeasurements2 { public static void main(String[] args) throws Exception { long start = System.currentTimeMillis(); - if (args.length != 1) { - System.out.println("Usage: create_measurements.sh "); + if (args.length < 1) { + System.out.println("Usage: create_measurements2.sh [seed]"); System.exit(1); } @@ -48,11 +49,24 @@ public static void main(String[] args) throws Exception { } catch (NumberFormatException e) { System.out.println("Invalid value for "); - System.out.println("Usage: CreateMeasurements "); + System.out.println("Usage: CreateMeasurements2 [seed]"); System.exit(1); } - final List stations = WeatherStation.getRandomWeatherStationsList(); + // Default seed is 1brc1brc converted to hexadecimal + long seed = 0x3162726331627263L; + if (args.length == 2) { + try { + seed = Long.parseLong(args[1]); + } + catch (NumberFormatException e) { + System.out.println("Invalid value for [seed]"); + System.out.println("Usage: CreateMeasurements2 [seed]"); + System.exit(1); + } + } + + final List stations = WeatherStationFactory.getWeatherStationsList(seed); File file = new File(FILE); @@ -60,16 +74,17 @@ public static void main(String[] args) throws Exception { int strideSize = 50_000_000; int outer = size / strideSize; int remainder = size - (outer * strideSize); + FastRandom random = new FastRandom(seed); try (final BufferedWriter bw = new BufferedWriter(new FileWriter(file))) { for (int i = 0; i < outer; i++) { - produce(bw, stations, strideSize); + produce(random, bw, stations, strideSize); // we avoid a modulo if here and use the stride size to print and update System.out.println("Wrote %,d measurements in %s ms".formatted((i + 1) * strideSize, System.currentTimeMillis() - start)); } // there might be a rest - produce(bw, stations, remainder); + produce(random, bw, stations, remainder); // write fully before taking measurements bw.flush(); @@ -77,17 +92,10 @@ public static void main(String[] args) throws Exception { } } - private static void produce(BufferedWriter bw, List stations, int count) throws IOException { + private static void produce(FastRandom random, BufferedWriter bw, List stations, int count) throws IOException { final int stationCount = stations.size(); final int rest = count % 8; - // use a fast ranodm impl without atomics to be able to utilize the cpu better - // and avoid sideeffects, FastRandom is very fake random and does not have a state - final FastRandom r1 = new FastRandom(ThreadLocalRandom.current().nextLong()); - final FastRandom r2 = new FastRandom(ThreadLocalRandom.current().nextLong()); - final FastRandom r3 = new FastRandom(ThreadLocalRandom.current().nextLong()); - final FastRandom r4 = new FastRandom(ThreadLocalRandom.current().nextLong()); - // write to a fix buffer first, don't create strings ever // reuse buffer final CheaperCharBuffer sb = new CheaperCharBuffer(200); @@ -97,35 +105,58 @@ private static void produce(BufferedWriter bw, List stations, in { // try to fill teh cpu pipeline as much as possible with // independent operations - int s1 = r1.nextInt(stationCount); - int s2 = r2.nextInt(stationCount); - int s3 = r3.nextInt(stationCount); - int s4 = r4.nextInt(stationCount); + int s1 = random.nextInt(stationCount); + int s2 = random.nextInt(stationCount); + int s3 = random.nextInt(stationCount); + int s4 = random.nextInt(stationCount); // get us the ojects one after the other to have the array // in our L1 cache and not push it out with other data var w1 = stations.get(s1); var w2 = stations.get(s2); var w3 = stations.get(s3); var w4 = stations.get(s4); + // write our data to our buffer + sb.append(w1.idChars, 0, w1.idChars.length).append(';'); w1.measurement(sb); + sb.append('\n'); + + sb.append(w2.idChars, 0, w2.idChars.length).append(';'); w2.measurement(sb); + sb.append('\n'); + + sb.append(w3.idChars, 0, w3.idChars.length).append(';'); w3.measurement(sb); + sb.append('\n'); + + sb.append(w4.idChars, 0, w4.idChars.length).append(';'); w4.measurement(sb); + sb.append('\n'); } { - int s1 = r1.nextInt(stationCount); - int s2 = r2.nextInt(stationCount); - int s3 = r3.nextInt(stationCount); - int s4 = r4.nextInt(stationCount); + int s1 = random.nextInt(stationCount); + int s2 = random.nextInt(stationCount); + int s3 = random.nextInt(stationCount); + int s4 = random.nextInt(stationCount); var w1 = stations.get(s1); var w2 = stations.get(s2); var w3 = stations.get(s3); var w4 = stations.get(s4); + sb.append(w1.idChars, 0, w1.idChars.length).append(';'); w1.measurement(sb); + sb.append('\n'); + + sb.append(w2.idChars, 0, w2.idChars.length).append(';'); w2.measurement(sb); + sb.append('\n'); + + sb.append(w3.idChars, 0, w3.idChars.length).append(';'); w3.measurement(sb); + sb.append('\n'); + + sb.append(w4.idChars, 0, w4.idChars.length).append(';'); w4.measurement(sb); + sb.append('\n'); } // write the buffer directly, no intermediate string copy bw.write(sb.data_, 0, sb.length_); @@ -138,9 +169,11 @@ private static void produce(BufferedWriter bw, List stations, in for (int i = 0; i < rest; i++) { sb.clear(); - int s = r1.nextInt(stationCount); + int s = random.nextInt(stationCount); var w = stations.get(s); + sb.append(w.idChars, 0, w.idChars.length).append(';'); w.measurement(sb); + sb.append('\n'); bw.write(sb.data_, 0, sb.length_); } diff --git a/src/main/java/dev/morling/onebrc/WeatherStation.java b/src/main/java/dev/morling/onebrc/WeatherStation.java index b5fb7c589..547e3f444 100644 --- a/src/main/java/dev/morling/onebrc/WeatherStation.java +++ b/src/main/java/dev/morling/onebrc/WeatherStation.java @@ -22,27 +22,38 @@ public class WeatherStation { final static char[] NUMBERS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; public final String id; + public final char[] idChars; public final double meanTemperature; - private final char[] firstPart; - private final Random random; private final FastRandom fastRandom; public WeatherStation(long seed, String id, double meanTemperature) { this.id = id; this.meanTemperature = meanTemperature; + this.fastRandom = new FastRandom(((long) id.hashCode()) ^ seed); + this.idChars = id.toCharArray(); + } - long rngSeed = ((long) id.hashCode()) ^ seed; - - this.random = new Random(rngSeed); - this.fastRandom = new FastRandom(rngSeed); + private int nextWholePart() { + // fake -10.9 to +10.9 variance without double operations and rounding + // gives us -10 to +10 + return (int) this.meanTemperature + (this.fastRandom.nextInt(21) - 10); + } - this.firstPart = (id + ";").toCharArray(); + private int nextDecimalPart() { + return this.fastRandom.nextInt(10); } public double measurement() { - double m = this.random.nextGaussian(this.meanTemperature, 10); - return Math.round(m * 10.0) / 10.0; + double whole = (double) this.nextWholePart(); + double decimal = (double) this.nextDecimalPart(); + + if (whole < 0) { + return whole - (decimal / 10.0); + } + else { + return whole + (decimal / 10.0); + } } /** @@ -53,17 +64,12 @@ public double measurement() { * @param buffer the buffer to append to */ public void measurement(final CheaperCharBuffer buffer) { - - // fake -10.9 to +10.9 variance without double operations and rounding - // gives us -10 to +10 - int m = (int) meanTemperature + (this.fastRandom.nextInt(21) - 10); + int m = this.nextWholePart(); // gives us a decimal digit 0 to 9 as char - char d = NUMBERS[this.fastRandom.nextInt(10)]; + char d = NUMBERS[this.nextDecimalPart()]; // just append, only one number has to be converted and we can do // better... if we watn - buffer.append(firstPart, 0, firstPart.length) - .append(String.valueOf(m)).append('.').append(d) - .append('\n'); + buffer.append(String.valueOf(m)).append('.').append(d); } } \ No newline at end of file From 43edd8c1db1734281e56ffff5520297bd71b796c Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Sat, 6 Jan 2024 12:02:41 +0000 Subject: [PATCH 5/8] Clean up import statements --- src/main/java/dev/morling/onebrc/CreateMeasurements.java | 3 --- src/main/java/dev/morling/onebrc/CreateMeasurements2.java | 3 --- 2 files changed, 6 deletions(-) diff --git a/src/main/java/dev/morling/onebrc/CreateMeasurements.java b/src/main/java/dev/morling/onebrc/CreateMeasurements.java index 59e51f0f5..b09e07db3 100644 --- a/src/main/java/dev/morling/onebrc/CreateMeasurements.java +++ b/src/main/java/dev/morling/onebrc/CreateMeasurements.java @@ -18,10 +18,7 @@ import java.io.BufferedWriter; import java.nio.file.Files; import java.nio.file.Path; -import java.util.Arrays; import java.util.List; -import java.util.concurrent.ThreadLocalRandom; -import java.util.Random; import org.rschwietzke.FastRandom; diff --git a/src/main/java/dev/morling/onebrc/CreateMeasurements2.java b/src/main/java/dev/morling/onebrc/CreateMeasurements2.java index 06b01dea8..31af25046 100644 --- a/src/main/java/dev/morling/onebrc/CreateMeasurements2.java +++ b/src/main/java/dev/morling/onebrc/CreateMeasurements2.java @@ -19,10 +19,7 @@ import java.io.File; import java.io.FileWriter; import java.io.IOException; -import java.util.Arrays; import java.util.List; -import java.util.Random; -import java.util.concurrent.ThreadLocalRandom; import org.rschwietzke.CheaperCharBuffer; import org.rschwietzke.FastRandom; From a0204aa5461919a1816fc5fcab8de53a2f055d44 Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Sat, 6 Jan 2024 12:10:26 +0000 Subject: [PATCH 6/8] Import new random station generation --- create_measurements3.sh | 2 +- .../morling/onebrc/CreateMeasurements3.java | 149 +---- .../morling/onebrc/WeatherStationFactory.java | 560 ++++-------------- src/main/java/org/rschwietzke/FastRandom.java | 4 + 4 files changed, 148 insertions(+), 567 deletions(-) diff --git a/create_measurements3.sh b/create_measurements3.sh index c5df5f99e..f0931e97d 100755 --- a/create_measurements3.sh +++ b/create_measurements3.sh @@ -16,4 +16,4 @@ # -java --class-path target/average-1.0.0-SNAPSHOT.jar dev.morling.onebrc.CreateMeasurements3 $1 +java --class-path target/average-1.0.0-SNAPSHOT.jar dev.morling.onebrc.CreateMeasurements3 $1 $2 diff --git a/src/main/java/dev/morling/onebrc/CreateMeasurements3.java b/src/main/java/dev/morling/onebrc/CreateMeasurements3.java index fb3a97d8c..92bb9a8d3 100644 --- a/src/main/java/dev/morling/onebrc/CreateMeasurements3.java +++ b/src/main/java/dev/morling/onebrc/CreateMeasurements3.java @@ -15,152 +15,57 @@ */ package dev.morling.onebrc; -import java.io.BufferedReader; import java.io.BufferedWriter; -import java.io.FileReader; import java.io.FileWriter; -import java.io.IOException; -import java.io.StringReader; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.concurrent.ThreadLocalRandom; -public class CreateMeasurements3 { +import org.rschwietzke.FastRandom; - public static final int MAX_NAME_LEN = 100; - public static final int KEYSET_SIZE = 10_000; +public class CreateMeasurements3 { public static void main(String[] args) throws Exception { - if (args.length != 1) { - System.out.println("Usage: create_measurements3.sh "); + if (args.length < 1) { + System.out.println("Usage: create_measurements3.sh [seed]"); System.exit(1); } + int size = 0; try { size = Integer.parseInt(args[0]); } catch (NumberFormatException e) { System.out.println("Invalid value for "); - System.out.println("Usage: create_measurements3.sh "); + System.out.println("Usage: create_measurements3.sh [seed]"); System.exit(1); } - final var weatherStations = generateWeatherStations(); + + // Default seed is 1brc1brc converted to hexadecimal + long seed = 0x3162726331627263L; + if (args.length == 2) { + try { + seed = Long.parseLong(args[1]); + } + catch (NumberFormatException e) { + System.out.println("Invalid value for [seed]"); + System.out.println("Usage: CreateMeasurements2 [seed]"); + System.exit(1); + } + } + + final var weatherStations = WeatherStationFactory.getWeatherStationsList(seed); final var start = System.currentTimeMillis(); - final var rnd = ThreadLocalRandom.current(); + final var rnd = new FastRandom(seed); try (var out = new BufferedWriter(new FileWriter("measurements.txt"))) { for (int i = 1; i <= size; i++) { - var station = weatherStations.get(rnd.nextInt(KEYSET_SIZE)); - double temp = rnd.nextGaussian(station.avgTemp, 7.0); - out.write(station.name); + var station = weatherStations.get(rnd.nextInt(weatherStations.size())); + double temp = station.measurement(); + out.write(station.id); out.write(';'); - out.write(Double.toString(Math.round(temp * 10.0) / 10.0)); - out.newLine(); + out.write(Double.toString(temp)); + out.write('\n'); if (i % 50_000_000 == 0) { System.out.printf("Wrote %,d measurements in %,d ms%n", i, System.currentTimeMillis() - start); } } } } - - record WeatherStation(String name, float avgTemp) { - } - - private static ArrayList generateWeatherStations() throws Exception { - // Use a public list of city names and concatenate them all into a long string, - // which we'll use as a "source of city name randomness" - var bigName = new StringBuilder(1 << 20); - try (var rows = new BufferedReader(new FileReader("data/weather_stations.csv"));) { - skipComments(rows); - while (true) { - var row = rows.readLine(); - if (row == null) { - break; - } - bigName.append(row, 0, row.indexOf(';')); - } - } - final var weatherStations = new ArrayList(); - final var names = new HashSet(); - var minLen = Integer.MAX_VALUE; - var maxLen = Integer.MIN_VALUE; - try (var rows = new BufferedReader(new FileReader("data/weather_stations.csv"))) { - skipComments(rows); - final var nameSource = new StringReader(bigName.toString()); - final var buf = new char[MAX_NAME_LEN]; - final var rnd = ThreadLocalRandom.current(); - final double yOffset = 4; - final double factor = 2500; - final double xOffset = 0.372; - final double power = 7; - for (int i = 0; i < KEYSET_SIZE; i++) { - var row = rows.readLine(); - if (row == null) { - break; - } - // Use a 7th-order curve to simulate the name length distribution. - // It gives us mostly short names, but with large outliers. - var nameLen = (int) (yOffset + factor * Math.pow(rnd.nextDouble() - xOffset, power)); - var count = nameSource.read(buf, 0, nameLen); - if (count == -1) { - throw new Exception("Name source exhausted"); - } - var nameBuf = new StringBuilder(nameLen); - nameBuf.append(buf, 0, nameLen); - if (Character.isWhitespace(nameBuf.charAt(0))) { - nameBuf.setCharAt(0, readNonSpace(nameSource)); - } - if (Character.isWhitespace(nameBuf.charAt(nameBuf.length() - 1))) { - nameBuf.setCharAt(nameBuf.length() - 1, readNonSpace(nameSource)); - } - var name = nameBuf.toString(); - while (names.contains(name)) { - nameBuf.setCharAt(rnd.nextInt(nameBuf.length()), readNonSpace(nameSource)); - name = nameBuf.toString(); - } - int actualLen; - while (true) { - actualLen = name.getBytes(StandardCharsets.UTF_8).length; - if (actualLen <= 100) { - break; - } - nameBuf.deleteCharAt(nameBuf.length() - 1); - if (Character.isWhitespace(nameBuf.charAt(nameBuf.length() - 1))) { - nameBuf.setCharAt(nameBuf.length() - 1, readNonSpace(nameSource)); - } - name = nameBuf.toString(); - } - if (name.indexOf(';') != -1) { - throw new Exception("Station name contains a semicolon!"); - } - names.add(name); - minLen = Integer.min(minLen, actualLen); - maxLen = Integer.max(maxLen, actualLen); - var lat = Float.parseFloat(row.substring(row.indexOf(';') + 1)); - // Guesstimate mean temperature using cosine of latitude - var avgTemp = (float) (30 * Math.cos(Math.toRadians(lat))) - 10; - weatherStations.add(new WeatherStation(name, avgTemp)); - } - } - System.out.format("Generated %,d station names with length from %,d to %,d%n", KEYSET_SIZE, minLen, maxLen); - return weatherStations; - } - - private static void skipComments(BufferedReader rows) throws IOException { - while (rows.readLine().startsWith("#")) { - } - } - - private static char readNonSpace(StringReader nameSource) throws IOException { - while (true) { - var n = nameSource.read(); - if (n == -1) { - throw new IOException("Name source exhausted"); - } - var ch = (char) n; - if (ch != ' ') { - return ch; - } - } - } } diff --git a/src/main/java/dev/morling/onebrc/WeatherStationFactory.java b/src/main/java/dev/morling/onebrc/WeatherStationFactory.java index a49938106..2d731043a 100644 --- a/src/main/java/dev/morling/onebrc/WeatherStationFactory.java +++ b/src/main/java/dev/morling/onebrc/WeatherStationFactory.java @@ -16,457 +16,129 @@ package dev.morling.onebrc; -import java.util.Arrays; -import java.util.Random; +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.io.StringReader; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.HashSet; import java.util.List; -import org.rschwietzke.CheaperCharBuffer; import org.rschwietzke.FastRandom; public class WeatherStationFactory { - public static List getRandomWeatherStationsList() { - return WeatherStationFactory.getWeatherStationsList(java.util.concurrent.ThreadLocalRandom.current().nextLong()); + private static final int MAX_NAME_LEN = 100; + private static final int KEYSET_SIZE = 10_000; + + public static List getRandomWeatherStationsList() throws Exception { + return WeatherStationFactory + .getWeatherStationsList(java.util.concurrent.ThreadLocalRandom.current().nextLong()); + } + + public static List getWeatherStationsList(long seed) throws Exception { + // Use a public list of city names and concatenate them all into a long string, + // which we'll use as a "source of city name randomness" + var bigName = new StringBuilder(1 << 20); + + try (var rows = new BufferedReader(new FileReader("data/weather_stations.csv"));) { + skipComments(rows); + while (true) { + var row = rows.readLine(); + if (row == null) { + break; + } + bigName.append(row, 0, row.indexOf(';')); + } + } + + final var weatherStations = new ArrayList(); + final var names = new HashSet(); + var minLen = Integer.MAX_VALUE; + var maxLen = Integer.MIN_VALUE; + try (var rows = new BufferedReader(new FileReader("data/weather_stations.csv"))) { + skipComments(rows); + final var rnd = new FastRandom(seed); + final var nameSource = new StringReader(bigName.toString()); + final var buf = new char[MAX_NAME_LEN]; + final double yOffset = 4; + final double factor = 2500; + final double xOffset = 0.372; + final double power = 7; + for (int i = 0; i < KEYSET_SIZE; i++) { + var row = rows.readLine(); + if (row == null) { + break; + } + // Use a 7th-order curve to simulate the name length distribution. + // It gives us mostly short names, but with large outliers. + var nameLen = (int) (yOffset + factor * Math.pow(rnd.nextDouble() - xOffset, power)); + var count = nameSource.read(buf, 0, nameLen); + if (count == -1) { + // TODO: Reset nameSource and read instead of throwing? + throw new Exception("Name source exhausted"); + } + + var nameBuf = new StringBuilder(nameLen); + nameBuf.append(buf, 0, nameLen); + + if (Character.isWhitespace(nameBuf.charAt(0))) { + nameBuf.setCharAt(0, readNonSpace(nameSource)); + } + if (Character.isWhitespace(nameBuf.charAt(nameBuf.length() - 1))) { + nameBuf.setCharAt(nameBuf.length() - 1, readNonSpace(nameSource)); + } + + var name = nameBuf.toString(); + int actualLen = name.getBytes(StandardCharsets.UTF_8).length; + while (actualLen > 100) { + nameBuf.deleteCharAt(nameBuf.length() - 1); + if (Character.isWhitespace(nameBuf.charAt(nameBuf.length() - 1))) { + nameBuf.setCharAt(nameBuf.length() - 1, readNonSpace(nameSource)); + } + name = nameBuf.toString(); + actualLen = name.getBytes(StandardCharsets.UTF_8).length; + } + + while (names.contains(name)) { + nameBuf.setCharAt(rnd.nextInt(nameBuf.length()), readNonSpace(nameSource)); + name = nameBuf.toString(); + } + + if (name.indexOf(';') != -1) { + throw new Exception("Station name contains a semicolon!"); + } + + names.add(name); + minLen = Integer.min(minLen, actualLen); + maxLen = Integer.max(maxLen, actualLen); + var lat = Double.parseDouble(row.substring(row.indexOf(';') + 1)); + // Guesstimate mean temperature using cosine of latitude + var avgTemp = (double) (30 * Math.cos(Math.toRadians(lat))) - 10; + weatherStations.add(new WeatherStation(seed, name, avgTemp)); + } + } + System.out.format("Generated %,d station names with length from %,d to %,d%n", KEYSET_SIZE, minLen, maxLen); + return weatherStations; } - public static List getWeatherStationsList(long seed) { - // @formatter:off - // data from https://en.wikipedia.org/wiki/List_of_cities_by_average_temperature; - // converted using https://wikitable2csv.ggor.de/ - // brought to form using DuckDB: - // D copy ( - // select City, regexp_extract(Year,'(.*)\n.*', 1) as AverageTemp - // from ( - // select City,Year - // from read_csv_auto('List_of_cities_by_average_temperature_1.csv', header = true) - // union - // select City,Year - // from read_csv_auto('List_of_cities_by_average_temperature_2.csv', header = true) - // union - // select City,Year - // from read_csv_auto('List_of_cities_by_average_temperature_3.csv', header = true) - // union - // select City,Year - // from read_csv_auto('List_of_cities_by_average_temperature_4.csv', header = true) - // union - // select City,Year - // from read_csv_auto('List_of_cities_by_average_temperature_5.csv', header = true) - // ) - // ) TO 'output.csv' (HEADER, DELIMITER ','); - // @formatter:on - return Arrays.asList( - new WeatherStation(seed, "Abha", 18.0), - new WeatherStation(seed, "Abidjan", 26.0), - new WeatherStation(seed, "Abéché", 29.4), - new WeatherStation(seed, "Accra", 26.4), - new WeatherStation(seed, "Addis Ababa", 16.0), - new WeatherStation(seed, "Adelaide", 17.3), - new WeatherStation(seed, "Aden", 29.1), - new WeatherStation(seed, "Ahvaz", 25.4), - new WeatherStation(seed, "Albuquerque", 14.0), - new WeatherStation(seed, "Alexandra", 11.0), - new WeatherStation(seed, "Alexandria", 20.0), - new WeatherStation(seed, "Algiers", 18.2), - new WeatherStation(seed, "Alice Springs", 21.0), - new WeatherStation(seed, "Almaty", 10.0), - new WeatherStation(seed, "Amsterdam", 10.2), - new WeatherStation(seed, "Anadyr", -6.9), - new WeatherStation(seed, "Anchorage", 2.8), - new WeatherStation(seed, "Andorra la Vella", 9.8), - new WeatherStation(seed, "Ankara", 12.0), - new WeatherStation(seed, "Antananarivo", 17.9), - new WeatherStation(seed, "Antsiranana", 25.2), - new WeatherStation(seed, "Arkhangelsk", 1.3), - new WeatherStation(seed, "Ashgabat", 17.1), - new WeatherStation(seed, "Asmara", 15.6), - new WeatherStation(seed, "Assab", 30.5), - new WeatherStation(seed, "Astana", 3.5), - new WeatherStation(seed, "Athens", 19.2), - new WeatherStation(seed, "Atlanta", 17.0), - new WeatherStation(seed, "Auckland", 15.2), - new WeatherStation(seed, "Austin", 20.7), - new WeatherStation(seed, "Baghdad", 22.77), - new WeatherStation(seed, "Baguio", 19.5), - new WeatherStation(seed, "Baku", 15.1), - new WeatherStation(seed, "Baltimore", 13.1), - new WeatherStation(seed, "Bamako", 27.8), - new WeatherStation(seed, "Bangkok", 28.6), - new WeatherStation(seed, "Bangui", 26.0), - new WeatherStation(seed, "Banjul", 26.0), - new WeatherStation(seed, "Barcelona", 18.2), - new WeatherStation(seed, "Bata", 25.1), - new WeatherStation(seed, "Batumi", 14.0), - new WeatherStation(seed, "Beijing", 12.9), - new WeatherStation(seed, "Beirut", 20.9), - new WeatherStation(seed, "Belgrade", 12.5), - new WeatherStation(seed, "Belize City", 26.7), - new WeatherStation(seed, "Benghazi", 19.9), - new WeatherStation(seed, "Bergen", 7.7), - new WeatherStation(seed, "Berlin", 10.3), - new WeatherStation(seed, "Bilbao", 14.7), - new WeatherStation(seed, "Birao", 26.5), - new WeatherStation(seed, "Bishkek", 11.3), - new WeatherStation(seed, "Bissau", 27.0), - new WeatherStation(seed, "Blantyre", 22.2), - new WeatherStation(seed, "Bloemfontein", 15.6), - new WeatherStation(seed, "Boise", 11.4), - new WeatherStation(seed, "Bordeaux", 14.2), - new WeatherStation(seed, "Bosaso", 30.0), - new WeatherStation(seed, "Boston", 10.9), - new WeatherStation(seed, "Bouaké", 26.0), - new WeatherStation(seed, "Bratislava", 10.5), - new WeatherStation(seed, "Brazzaville", 25.0), - new WeatherStation(seed, "Bridgetown", 27.0), - new WeatherStation(seed, "Brisbane", 21.4), - new WeatherStation(seed, "Brussels", 10.5), - new WeatherStation(seed, "Bucharest", 10.8), - new WeatherStation(seed, "Budapest", 11.3), - new WeatherStation(seed, "Bujumbura", 23.8), - new WeatherStation(seed, "Bulawayo", 18.9), - new WeatherStation(seed, "Burnie", 13.1), - new WeatherStation(seed, "Busan", 15.0), - new WeatherStation(seed, "Cabo San Lucas", 23.9), - new WeatherStation(seed, "Cairns", 25.0), - new WeatherStation(seed, "Cairo", 21.4), - new WeatherStation(seed, "Calgary", 4.4), - new WeatherStation(seed, "Canberra", 13.1), - new WeatherStation(seed, "Cape Town", 16.2), - new WeatherStation(seed, "Changsha", 17.4), - new WeatherStation(seed, "Charlotte", 16.1), - new WeatherStation(seed, "Chiang Mai", 25.8), - new WeatherStation(seed, "Chicago", 9.8), - new WeatherStation(seed, "Chihuahua", 18.6), - new WeatherStation(seed, "Chișinău", 10.2), - new WeatherStation(seed, "Chittagong", 25.9), - new WeatherStation(seed, "Chongqing", 18.6), - new WeatherStation(seed, "Christchurch", 12.2), - new WeatherStation(seed, "City of San Marino", 11.8), - new WeatherStation(seed, "Colombo", 27.4), - new WeatherStation(seed, "Columbus", 11.7), - new WeatherStation(seed, "Conakry", 26.4), - new WeatherStation(seed, "Copenhagen", 9.1), - new WeatherStation(seed, "Cotonou", 27.2), - new WeatherStation(seed, "Cracow", 9.3), - new WeatherStation(seed, "Da Lat", 17.9), - new WeatherStation(seed, "Da Nang", 25.8), - new WeatherStation(seed, "Dakar", 24.0), - new WeatherStation(seed, "Dallas", 19.0), - new WeatherStation(seed, "Damascus", 17.0), - new WeatherStation(seed, "Dampier", 26.4), - new WeatherStation(seed, "Dar es Salaam", 25.8), - new WeatherStation(seed, "Darwin", 27.6), - new WeatherStation(seed, "Denpasar", 23.7), - new WeatherStation(seed, "Denver", 10.4), - new WeatherStation(seed, "Detroit", 10.0), - new WeatherStation(seed, "Dhaka", 25.9), - new WeatherStation(seed, "Dikson", -11.1), - new WeatherStation(seed, "Dili", 26.6), - new WeatherStation(seed, "Djibouti", 29.9), - new WeatherStation(seed, "Dodoma", 22.7), - new WeatherStation(seed, "Dolisie", 24.0), - new WeatherStation(seed, "Douala", 26.7), - new WeatherStation(seed, "Dubai", 26.9), - new WeatherStation(seed, "Dublin", 9.8), - new WeatherStation(seed, "Dunedin", 11.1), - new WeatherStation(seed, "Durban", 20.6), - new WeatherStation(seed, "Dushanbe", 14.7), - new WeatherStation(seed, "Edinburgh", 9.3), - new WeatherStation(seed, "Edmonton", 4.2), - new WeatherStation(seed, "El Paso", 18.1), - new WeatherStation(seed, "Entebbe", 21.0), - new WeatherStation(seed, "Erbil", 19.5), - new WeatherStation(seed, "Erzurum", 5.1), - new WeatherStation(seed, "Fairbanks", -2.3), - new WeatherStation(seed, "Fianarantsoa", 17.9), - new WeatherStation(seed, "Flores, Petén", 26.4), - new WeatherStation(seed, "Frankfurt", 10.6), - new WeatherStation(seed, "Fresno", 17.9), - new WeatherStation(seed, "Fukuoka", 17.0), - new WeatherStation(seed, "Gabès", 19.5), - new WeatherStation(seed, "Gaborone", 21.0), - new WeatherStation(seed, "Gagnoa", 26.0), - new WeatherStation(seed, "Gangtok", 15.2), - new WeatherStation(seed, "Garissa", 29.3), - new WeatherStation(seed, "Garoua", 28.3), - new WeatherStation(seed, "George Town", 27.9), - new WeatherStation(seed, "Ghanzi", 21.4), - new WeatherStation(seed, "Gjoa Haven", -14.4), - new WeatherStation(seed, "Guadalajara", 20.9), - new WeatherStation(seed, "Guangzhou", 22.4), - new WeatherStation(seed, "Guatemala City", 20.4), - new WeatherStation(seed, "Halifax", 7.5), - new WeatherStation(seed, "Hamburg", 9.7), - new WeatherStation(seed, "Hamilton", 13.8), - new WeatherStation(seed, "Hanga Roa", 20.5), - new WeatherStation(seed, "Hanoi", 23.6), - new WeatherStation(seed, "Harare", 18.4), - new WeatherStation(seed, "Harbin", 5.0), - new WeatherStation(seed, "Hargeisa", 21.7), - new WeatherStation(seed, "Hat Yai", 27.0), - new WeatherStation(seed, "Havana", 25.2), - new WeatherStation(seed, "Helsinki", 5.9), - new WeatherStation(seed, "Heraklion", 18.9), - new WeatherStation(seed, "Hiroshima", 16.3), - new WeatherStation(seed, "Ho Chi Minh City", 27.4), - new WeatherStation(seed, "Hobart", 12.7), - new WeatherStation(seed, "Hong Kong", 23.3), - new WeatherStation(seed, "Honiara", 26.5), - new WeatherStation(seed, "Honolulu", 25.4), - new WeatherStation(seed, "Houston", 20.8), - new WeatherStation(seed, "Ifrane", 11.4), - new WeatherStation(seed, "Indianapolis", 11.8), - new WeatherStation(seed, "Iqaluit", -9.3), - new WeatherStation(seed, "Irkutsk", 1.0), - new WeatherStation(seed, "Istanbul", 13.9), - new WeatherStation(seed, "İzmir", 17.9), - new WeatherStation(seed, "Jacksonville", 20.3), - new WeatherStation(seed, "Jakarta", 26.7), - new WeatherStation(seed, "Jayapura", 27.0), - new WeatherStation(seed, "Jerusalem", 18.3), - new WeatherStation(seed, "Johannesburg", 15.5), - new WeatherStation(seed, "Jos", 22.8), - new WeatherStation(seed, "Juba", 27.8), - new WeatherStation(seed, "Kabul", 12.1), - new WeatherStation(seed, "Kampala", 20.0), - new WeatherStation(seed, "Kandi", 27.7), - new WeatherStation(seed, "Kankan", 26.5), - new WeatherStation(seed, "Kano", 26.4), - new WeatherStation(seed, "Kansas City", 12.5), - new WeatherStation(seed, "Karachi", 26.0), - new WeatherStation(seed, "Karonga", 24.4), - new WeatherStation(seed, "Kathmandu", 18.3), - new WeatherStation(seed, "Khartoum", 29.9), - new WeatherStation(seed, "Kingston", 27.4), - new WeatherStation(seed, "Kinshasa", 25.3), - new WeatherStation(seed, "Kolkata", 26.7), - new WeatherStation(seed, "Kuala Lumpur", 27.3), - new WeatherStation(seed, "Kumasi", 26.0), - new WeatherStation(seed, "Kunming", 15.7), - new WeatherStation(seed, "Kuopio", 3.4), - new WeatherStation(seed, "Kuwait City", 25.7), - new WeatherStation(seed, "Kyiv", 8.4), - new WeatherStation(seed, "Kyoto", 15.8), - new WeatherStation(seed, "La Ceiba", 26.2), - new WeatherStation(seed, "La Paz", 23.7), - new WeatherStation(seed, "Lagos", 26.8), - new WeatherStation(seed, "Lahore", 24.3), - new WeatherStation(seed, "Lake Havasu City", 23.7), - new WeatherStation(seed, "Lake Tekapo", 8.7), - new WeatherStation(seed, "Las Palmas de Gran Canaria", 21.2), - new WeatherStation(seed, "Las Vegas", 20.3), - new WeatherStation(seed, "Launceston", 13.1), - new WeatherStation(seed, "Lhasa", 7.6), - new WeatherStation(seed, "Libreville", 25.9), - new WeatherStation(seed, "Lisbon", 17.5), - new WeatherStation(seed, "Livingstone", 21.8), - new WeatherStation(seed, "Ljubljana", 10.9), - new WeatherStation(seed, "Lodwar", 29.3), - new WeatherStation(seed, "Lomé", 26.9), - new WeatherStation(seed, "London", 11.3), - new WeatherStation(seed, "Los Angeles", 18.6), - new WeatherStation(seed, "Louisville", 13.9), - new WeatherStation(seed, "Luanda", 25.8), - new WeatherStation(seed, "Lubumbashi", 20.8), - new WeatherStation(seed, "Lusaka", 19.9), - new WeatherStation(seed, "Luxembourg City", 9.3), - new WeatherStation(seed, "Lviv", 7.8), - new WeatherStation(seed, "Lyon", 12.5), - new WeatherStation(seed, "Madrid", 15.0), - new WeatherStation(seed, "Mahajanga", 26.3), - new WeatherStation(seed, "Makassar", 26.7), - new WeatherStation(seed, "Makurdi", 26.0), - new WeatherStation(seed, "Malabo", 26.3), - new WeatherStation(seed, "Malé", 28.0), - new WeatherStation(seed, "Managua", 27.3), - new WeatherStation(seed, "Manama", 26.5), - new WeatherStation(seed, "Mandalay", 28.0), - new WeatherStation(seed, "Mango", 28.1), - new WeatherStation(seed, "Manila", 28.4), - new WeatherStation(seed, "Maputo", 22.8), - new WeatherStation(seed, "Marrakesh", 19.6), - new WeatherStation(seed, "Marseille", 15.8), - new WeatherStation(seed, "Maun", 22.4), - new WeatherStation(seed, "Medan", 26.5), - new WeatherStation(seed, "Mek'ele", 22.7), - new WeatherStation(seed, "Melbourne", 15.1), - new WeatherStation(seed, "Memphis", 17.2), - new WeatherStation(seed, "Mexicali", 23.1), - new WeatherStation(seed, "Mexico City", 17.5), - new WeatherStation(seed, "Miami", 24.9), - new WeatherStation(seed, "Milan", 13.0), - new WeatherStation(seed, "Milwaukee", 8.9), - new WeatherStation(seed, "Minneapolis", 7.8), - new WeatherStation(seed, "Minsk", 6.7), - new WeatherStation(seed, "Mogadishu", 27.1), - new WeatherStation(seed, "Mombasa", 26.3), - new WeatherStation(seed, "Monaco", 16.4), - new WeatherStation(seed, "Moncton", 6.1), - new WeatherStation(seed, "Monterrey", 22.3), - new WeatherStation(seed, "Montreal", 6.8), - new WeatherStation(seed, "Moscow", 5.8), - new WeatherStation(seed, "Mumbai", 27.1), - new WeatherStation(seed, "Murmansk", 0.6), - new WeatherStation(seed, "Muscat", 28.0), - new WeatherStation(seed, "Mzuzu", 17.7), - new WeatherStation(seed, "N'Djamena", 28.3), - new WeatherStation(seed, "Naha", 23.1), - new WeatherStation(seed, "Nairobi", 17.8), - new WeatherStation(seed, "Nakhon Ratchasima", 27.3), - new WeatherStation(seed, "Napier", 14.6), - new WeatherStation(seed, "Napoli", 15.9), - new WeatherStation(seed, "Nashville", 15.4), - new WeatherStation(seed, "Nassau", 24.6), - new WeatherStation(seed, "Ndola", 20.3), - new WeatherStation(seed, "New Delhi", 25.0), - new WeatherStation(seed, "New Orleans", 20.7), - new WeatherStation(seed, "New York City", 12.9), - new WeatherStation(seed, "Ngaoundéré", 22.0), - new WeatherStation(seed, "Niamey", 29.3), - new WeatherStation(seed, "Nicosia", 19.7), - new WeatherStation(seed, "Niigata", 13.9), - new WeatherStation(seed, "Nouadhibou", 21.3), - new WeatherStation(seed, "Nouakchott", 25.7), - new WeatherStation(seed, "Novosibirsk", 1.7), - new WeatherStation(seed, "Nuuk", -1.4), - new WeatherStation(seed, "Odesa", 10.7), - new WeatherStation(seed, "Odienné", 26.0), - new WeatherStation(seed, "Oklahoma City", 15.9), - new WeatherStation(seed, "Omaha", 10.6), - new WeatherStation(seed, "Oranjestad", 28.1), - new WeatherStation(seed, "Oslo", 5.7), - new WeatherStation(seed, "Ottawa", 6.6), - new WeatherStation(seed, "Ouagadougou", 28.3), - new WeatherStation(seed, "Ouahigouya", 28.6), - new WeatherStation(seed, "Ouarzazate", 18.9), - new WeatherStation(seed, "Oulu", 2.7), - new WeatherStation(seed, "Palembang", 27.3), - new WeatherStation(seed, "Palermo", 18.5), - new WeatherStation(seed, "Palm Springs", 24.5), - new WeatherStation(seed, "Palmerston North", 13.2), - new WeatherStation(seed, "Panama City", 28.0), - new WeatherStation(seed, "Parakou", 26.8), - new WeatherStation(seed, "Paris", 12.3), - new WeatherStation(seed, "Perth", 18.7), - new WeatherStation(seed, "Petropavlovsk-Kamchatsky", 1.9), - new WeatherStation(seed, "Philadelphia", 13.2), - new WeatherStation(seed, "Phnom Penh", 28.3), - new WeatherStation(seed, "Phoenix", 23.9), - new WeatherStation(seed, "Pittsburgh", 10.8), - new WeatherStation(seed, "Podgorica", 15.3), - new WeatherStation(seed, "Pointe-Noire", 26.1), - new WeatherStation(seed, "Pontianak", 27.7), - new WeatherStation(seed, "Port Moresby", 26.9), - new WeatherStation(seed, "Port Sudan", 28.4), - new WeatherStation(seed, "Port Vila", 24.3), - new WeatherStation(seed, "Port-Gentil", 26.0), - new WeatherStation(seed, "Portland (OR)", 12.4), - new WeatherStation(seed, "Porto", 15.7), - new WeatherStation(seed, "Prague", 8.4), - new WeatherStation(seed, "Praia", 24.4), - new WeatherStation(seed, "Pretoria", 18.2), - new WeatherStation(seed, "Pyongyang", 10.8), - new WeatherStation(seed, "Rabat", 17.2), - new WeatherStation(seed, "Rangpur", 24.4), - new WeatherStation(seed, "Reggane", 28.3), - new WeatherStation(seed, "Reykjavík", 4.3), - new WeatherStation(seed, "Riga", 6.2), - new WeatherStation(seed, "Riyadh", 26.0), - new WeatherStation(seed, "Rome", 15.2), - new WeatherStation(seed, "Roseau", 26.2), - new WeatherStation(seed, "Rostov-on-Don", 9.9), - new WeatherStation(seed, "Sacramento", 16.3), - new WeatherStation(seed, "Saint Petersburg", 5.8), - new WeatherStation(seed, "Saint-Pierre", 5.7), - new WeatherStation(seed, "Salt Lake City", 11.6), - new WeatherStation(seed, "San Antonio", 20.8), - new WeatherStation(seed, "San Diego", 17.8), - new WeatherStation(seed, "San Francisco", 14.6), - new WeatherStation(seed, "San Jose", 16.4), - new WeatherStation(seed, "San José", 22.6), - new WeatherStation(seed, "San Juan", 27.2), - new WeatherStation(seed, "San Salvador", 23.1), - new WeatherStation(seed, "Sana'a", 20.0), - new WeatherStation(seed, "Santo Domingo", 25.9), - new WeatherStation(seed, "Sapporo", 8.9), - new WeatherStation(seed, "Sarajevo", 10.1), - new WeatherStation(seed, "Saskatoon", 3.3), - new WeatherStation(seed, "Seattle", 11.3), - new WeatherStation(seed, "Ségou", 28.0), - new WeatherStation(seed, "Seoul", 12.5), - new WeatherStation(seed, "Seville", 19.2), - new WeatherStation(seed, "Shanghai", 16.7), - new WeatherStation(seed, "Singapore", 27.0), - new WeatherStation(seed, "Skopje", 12.4), - new WeatherStation(seed, "Sochi", 14.2), - new WeatherStation(seed, "Sofia", 10.6), - new WeatherStation(seed, "Sokoto", 28.0), - new WeatherStation(seed, "Split", 16.1), - new WeatherStation(seed, "St. John's", 5.0), - new WeatherStation(seed, "St. Louis", 13.9), - new WeatherStation(seed, "Stockholm", 6.6), - new WeatherStation(seed, "Surabaya", 27.1), - new WeatherStation(seed, "Suva", 25.6), - new WeatherStation(seed, "Suwałki", 7.2), - new WeatherStation(seed, "Sydney", 17.7), - new WeatherStation(seed, "Tabora", 23.0), - new WeatherStation(seed, "Tabriz", 12.6), - new WeatherStation(seed, "Taipei", 23.0), - new WeatherStation(seed, "Tallinn", 6.4), - new WeatherStation(seed, "Tamale", 27.9), - new WeatherStation(seed, "Tamanrasset", 21.7), - new WeatherStation(seed, "Tampa", 22.9), - new WeatherStation(seed, "Tashkent", 14.8), - new WeatherStation(seed, "Tauranga", 14.8), - new WeatherStation(seed, "Tbilisi", 12.9), - new WeatherStation(seed, "Tegucigalpa", 21.7), - new WeatherStation(seed, "Tehran", 17.0), - new WeatherStation(seed, "Tel Aviv", 20.0), - new WeatherStation(seed, "Thessaloniki", 16.0), - new WeatherStation(seed, "Thiès", 24.0), - new WeatherStation(seed, "Tijuana", 17.8), - new WeatherStation(seed, "Timbuktu", 28.0), - new WeatherStation(seed, "Tirana", 15.2), - new WeatherStation(seed, "Toamasina", 23.4), - new WeatherStation(seed, "Tokyo", 15.4), - new WeatherStation(seed, "Toliara", 24.1), - new WeatherStation(seed, "Toluca", 12.4), - new WeatherStation(seed, "Toronto", 9.4), - new WeatherStation(seed, "Tripoli", 20.0), - new WeatherStation(seed, "Tromsø", 2.9), - new WeatherStation(seed, "Tucson", 20.9), - new WeatherStation(seed, "Tunis", 18.4), - new WeatherStation(seed, "Ulaanbaatar", -0.4), - new WeatherStation(seed, "Upington", 20.4), - new WeatherStation(seed, "Ürümqi", 7.4), - new WeatherStation(seed, "Vaduz", 10.1), - new WeatherStation(seed, "Valencia", 18.3), - new WeatherStation(seed, "Valletta", 18.8), - new WeatherStation(seed, "Vancouver", 10.4), - new WeatherStation(seed, "Veracruz", 25.4), - new WeatherStation(seed, "Vienna", 10.4), - new WeatherStation(seed, "Vientiane", 25.9), - new WeatherStation(seed, "Villahermosa", 27.1), - new WeatherStation(seed, "Vilnius", 6.0), - new WeatherStation(seed, "Virginia Beach", 15.8), - new WeatherStation(seed, "Vladivostok", 4.9), - new WeatherStation(seed, "Warsaw", 8.5), - new WeatherStation(seed, "Washington, D.C.", 14.6), - new WeatherStation(seed, "Wau", 27.8), - new WeatherStation(seed, "Wellington", 12.9), - new WeatherStation(seed, "Whitehorse", -0.1), - new WeatherStation(seed, "Wichita", 13.9), - new WeatherStation(seed, "Willemstad", 28.0), - new WeatherStation(seed, "Winnipeg", 3.0), - new WeatherStation(seed, "Wrocław", 9.6), - new WeatherStation(seed, "Xi'an", 14.1), - new WeatherStation(seed, "Yakutsk", -8.8), - new WeatherStation(seed, "Yangon", 27.5), - new WeatherStation(seed, "Yaoundé", 23.8), - new WeatherStation(seed, "Yellowknife", -4.3), - new WeatherStation(seed, "Yerevan", 12.4), - new WeatherStation(seed, "Yinchuan", 9.0), - new WeatherStation(seed, "Zagreb", 10.7), - new WeatherStation(seed, "Zanzibar City", 26.0), - new WeatherStation(seed, "Zürich", 9.3)); + private static void skipComments(BufferedReader rows) throws IOException { + while (rows.readLine().startsWith("#")) { + } + } + + private static char readNonSpace(StringReader nameSource) throws Exception { + char c; + do { + var n = nameSource.read(); + if (n == -1) { + // TODO: Reset nameSource and read instead of throwing? + throw new Exception("Name source exhausted"); + } + c = (char) n; + } while (c == ' '); + + return c; } } \ No newline at end of file diff --git a/src/main/java/org/rschwietzke/FastRandom.java b/src/main/java/org/rschwietzke/FastRandom.java index 2d25d3540..b6bbdad17 100644 --- a/src/main/java/org/rschwietzke/FastRandom.java +++ b/src/main/java/org/rschwietzke/FastRandom.java @@ -73,4 +73,8 @@ public int nextInt(int bound) { public int nextInt() { return next(32); } + + public double nextDouble() { + return (double) Math.abs(this.nextInt()) / (double) Integer.MAX_VALUE; + } } From ccdeb901222f15e28d5be696425e98fe87709eb6 Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Sat, 6 Jan 2024 16:41:09 +0000 Subject: [PATCH 7/8] Avoid creating station names > 100 bytes long --- .../morling/onebrc/WeatherStationFactory.java | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/main/java/dev/morling/onebrc/WeatherStationFactory.java b/src/main/java/dev/morling/onebrc/WeatherStationFactory.java index 2d731043a..0252fe273 100644 --- a/src/main/java/dev/morling/onebrc/WeatherStationFactory.java +++ b/src/main/java/dev/morling/onebrc/WeatherStationFactory.java @@ -91,19 +91,23 @@ public static List getWeatherStationsList(long seed) throws Exce } var name = nameBuf.toString(); - int actualLen = name.getBytes(StandardCharsets.UTF_8).length; - while (actualLen > 100) { - nameBuf.deleteCharAt(nameBuf.length() - 1); - if (Character.isWhitespace(nameBuf.charAt(nameBuf.length() - 1))) { - nameBuf.setCharAt(nameBuf.length() - 1, readNonSpace(nameSource)); + int nameByteLen = name.getBytes(StandardCharsets.UTF_8).length; + + while (names.contains(name) || nameByteLen > 100) { + // If the character length is over 100 + if (nameByteLen > 100) { + nameBuf.deleteCharAt(nameBuf.length() - 1); + if (Character.isWhitespace(nameBuf.charAt(nameBuf.length() - 1))) { + nameBuf.setCharAt(nameBuf.length() - 1, readNonSpace(nameSource)); + } + } + // Else: name is not unique + else { + nameBuf.setCharAt(rnd.nextInt(nameBuf.length()), readNonSpace(nameSource)); } - name = nameBuf.toString(); - actualLen = name.getBytes(StandardCharsets.UTF_8).length; - } - while (names.contains(name)) { - nameBuf.setCharAt(rnd.nextInt(nameBuf.length()), readNonSpace(nameSource)); name = nameBuf.toString(); + nameByteLen = name.getBytes(StandardCharsets.UTF_8).length; } if (name.indexOf(';') != -1) { @@ -111,8 +115,8 @@ public static List getWeatherStationsList(long seed) throws Exce } names.add(name); - minLen = Integer.min(minLen, actualLen); - maxLen = Integer.max(maxLen, actualLen); + minLen = Integer.min(minLen, nameByteLen); + maxLen = Integer.max(maxLen, nameByteLen); var lat = Double.parseDouble(row.substring(row.indexOf(';') + 1)); // Guesstimate mean temperature using cosine of latitude var avgTemp = (double) (30 * Math.cos(Math.toRadians(lat))) - 10; From fce2b1ecd5b30a0280aa0bffbc44af09c41c5af7 Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Sat, 6 Jan 2024 18:36:16 +0000 Subject: [PATCH 8/8] while Character.isWhiteSpace --- src/main/java/dev/morling/onebrc/WeatherStationFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/dev/morling/onebrc/WeatherStationFactory.java b/src/main/java/dev/morling/onebrc/WeatherStationFactory.java index 0252fe273..ff6c6a10c 100644 --- a/src/main/java/dev/morling/onebrc/WeatherStationFactory.java +++ b/src/main/java/dev/morling/onebrc/WeatherStationFactory.java @@ -141,7 +141,7 @@ private static char readNonSpace(StringReader nameSource) throws Exception { throw new Exception("Name source exhausted"); } c = (char) n; - } while (c == ' '); + } while (Character.isWhitespace(c)); return c; }