From f4d849dd0188269be0c01435c104f2a1ef93ef3a Mon Sep 17 00:00:00 2001 From: tferrara3 Date: Wed, 31 Jan 2024 12:56:29 +0100 Subject: [PATCH] submit --- calculate_average_Freyrr.sh | 26 ++++ prepare_Freyrr.sh | 38 ++++++ .../onebrc/CalculateAverage_Freyrr.java | 122 ++++++++++++++++++ 3 files changed, 186 insertions(+) create mode 100644 calculate_average_Freyrr.sh create mode 100644 prepare_Freyrr.sh create mode 100644 src/main/java/dev/morling/onebrc/CalculateAverage_Freyrr.java diff --git a/calculate_average_Freyrr.sh b/calculate_average_Freyrr.sh new file mode 100644 index 000000000..b7df9b85e --- /dev/null +++ b/calculate_average_Freyrr.sh @@ -0,0 +1,26 @@ +#!/bin/sh +# +# Copyright 2023 The original authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +if [ -f target/CalculateAverage_Freyrr_image ]; then + echo "Picking up existing native image 'target/CalculateAverage_Freyrr_image', delete the file to select JVM mode." 1>&2 + target/CalculateAverage_Freyrr_image +else + JAVA_OPTS="--enable-preview" + echo "Chosing to run the app in JVM mode as no native image was found, use prepare_Freyrr.sh to generate." 1>&2 + java $JAVA_OPTS --class-path target/average-1.0.0-SNAPSHOT.jar dev.morling.onebrc.CalculateAverage_Freyrr +fi + diff --git a/prepare_Freyrr.sh b/prepare_Freyrr.sh new file mode 100644 index 000000000..16aee715b --- /dev/null +++ b/prepare_Freyrr.sh @@ -0,0 +1,38 @@ +#!/bin/bash +# +# 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. +# + +source "$HOME/.sdkman/bin/sdkman-init.sh" +sdk use java 21.0.2-graal 1>&2 + +# ./mvnw clean verify removes target/ and will re-trigger native image creation. +if [ ! -f target/CalculateAverage_Freyrr_image ]; then + + # Performance tuning flags, optimization level 3, maximum inlining exploration, and compile for the architecture where the native image is generated. + NATIVE_IMAGE_OPTS="-O3 -H:TuneInlinerExploration=1 -march=native" + + # Need to enable preview for accessing the raw address of the foreign memory access API. + # Initializing the Scanner to make sure the unsafe access object is known as a non-null compile time constant. + NATIVE_IMAGE_OPTS="$NATIVE_IMAGE_OPTS --enable-preview --initialize-at-build-time=dev.morling.onebrc.CalculateAverage_Freyrr\$Scanner" + + # There is no need for garbage collection and therefore also no safepoints required. + NATIVE_IMAGE_OPTS="$NATIVE_IMAGE_OPTS --gc=epsilon -H:-GenLoopSafepoints" + + # Uncomment the following line for outputting the compiler graph to the IdealGraphVisualizer + # NATIVE_IMAGE_OPTS="$NATIVE_IMAGE_OPTS -H:MethodFilter=CalculateAverage_Freyrr.* -H:Dump=:2 -H:PrintGraph=Network" + + native-image $NATIVE_IMAGE_OPTS -cp target/average-1.0.0-SNAPSHOT.jar -o target/CalculateAverage_Freyrr_image dev.morling.onebrc.CalculateAverage_Freyrr +fi diff --git a/src/main/java/dev/morling/onebrc/CalculateAverage_Freyrr.java b/src/main/java/dev/morling/onebrc/CalculateAverage_Freyrr.java new file mode 100644 index 000000000..1f8648d03 --- /dev/null +++ b/src/main/java/dev/morling/onebrc/CalculateAverage_Freyrr.java @@ -0,0 +1,122 @@ +/* + * 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.io.BufferedReader; +import java.io.FileReader; +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; + + + +public class CalculateAverage_Freyrr { + private static final String FILE = "./measurements.txt"; + public static void main(String[] args) { + + try { + Map cityStats = processFile(FILE); + printCityStats(cityStats); + } catch (Exception e) { + e.printStackTrace(); + } + } + + + private static Map processFile(String filePath) throws Exception { + Map cityStats = new HashMap<>(); + + try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) { + String line; + while ((line = reader.readLine()) != null) { + String[] parts = line.split(";"); + if (parts.length == 2) { + String city = parts[0]; + double temperature = Double.parseDouble(parts[1]); + + TemperatureStats stats = cityStats.getOrDefault(city, new TemperatureStats()); + stats.update(temperature); + cityStats.put(city, stats); + } + } + } + + return cityStats; + } + + private static void printCityStats(Map cityStats) { + for (Map.Entry entry : cityStats.entrySet()) { + String city = entry.getKey(); + TemperatureStats stats = entry.getValue(); + System.out.println(city +"=" + round(stats.getMinTemperature() / 10.0) + + "/" + round(stats.getMaxTemperature() / 10.0) + + "/" + round(stats.getAverageTemperature() / 10.0)); + } + } + + private static double round(double value) { + return Math.round(value * 10.0) / 10.0; + } + + static class TemperatureStats { + private double minTemperature = Double.MAX_VALUE; + private double maxTemperature = Double.MIN_VALUE; + private double totalTemperature = 0.0; + private int count = 0; + + public void update(double temperature) { + minTemperature = Math.min(minTemperature, temperature); + maxTemperature = Math.max(maxTemperature, temperature); + totalTemperature += temperature; + count++; + } + + public double getMinTemperature() { + return minTemperature; + } + + public double getMaxTemperature() { + return maxTemperature; + } + + public double getAverageTemperature() { + return count > 0 ? totalTemperature / count : 0.0; + } + } + + static class UnsafeUtils { + private static final Unsafe unsafe; + + static { + try { + Field field = Unsafe.class.getDeclaredField("theUnsafe"); + field.setAccessible(true); + unsafe = (Unsafe) field.get(null); + } catch (Exception e) { + throw new RuntimeException("Failed to obtain Unsafe instance", e); + } + } + + static double getDouble(Object obj, long offset) { + return unsafe.getDouble(obj, offset); + } + + static void putDouble(Object obj, long offset, double value) { + unsafe.putDouble(obj, offset, value); + } + } +}