diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..3550a30 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3906c5c --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +target +result +.direnv diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..296bf15 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 0000000..712ab9d --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..85eb9dc --- /dev/null +++ b/README.md @@ -0,0 +1,12 @@ + +``` +# VM version: JDK 22.0.2, OpenJDK 64-Bit Server VM, 22.0.2+9-jvmci-b01 +# VM invoker: /nix/store/lschm1if5f45qf8zwr5z7h0afhd00gd4-graalvm-ce-22.0.2/bin/java +# VM options: -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCIProduct -XX:-UnlockExperimentalVMOptions -javaagent:/nix/store/0y08ljcqmrqrcmjcx7zvx9k3haifhx0q-idea-ultimate-2024.2.0.2/idea-ultimate/lib/idea_rt.jar=40733:/nix/store/0y08ljcqmrqrcmjcx7zvx9k3haifhx0q-idea-ultimate-2024.2.0.2/idea-ultimate/bin -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 +# Blackhole mode: compiler (auto-detected, use -Djmh.blackhole.autoDetect=false to disable) + +Benchmark Mode Cnt Score Error Units +Main.brokenDownWithMethods thrpt 25 6815.783 ± 106.436 ops/s +Main.brokenDownWithMethodsWithStreams thrpt 25 6178.742 ± 85.668 ops/s +Main.classical thrpt 25 5780.151 ± 19.606 ops/s +``` diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..d0af478 --- /dev/null +++ b/flake.lock @@ -0,0 +1,61 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1725634671, + "narHash": "sha256-v3rIhsJBOMLR8e/RNWxr828tB+WywYIoajrZKFM+0Gg=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "574d1eac1c200690e27b8eb4e24887f8df7ac27c", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs", + "utils": "utils" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..f1241f7 --- /dev/null +++ b/flake.nix @@ -0,0 +1,43 @@ +{ + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; + utils.url = "github:numtide/flake-utils"; + }; + outputs = { self, nixpkgs, utils }: utils.lib.eachDefaultSystem (system: + let + pkgs = nixpkgs.legacyPackages.${system}; + pname = "stream-examples"; + benchmark = pkgs.maven.buildMavenPackage { + mvnJdk = pkgs.jdk22; + pname = pname; + version = "0.1.0"; + src = ./.; + nativeBuildInputs = [ pkgs.makeWrapper ]; + mvnHash = "sha256-G7PQd0Ul61m+C9S7OvAB6NkMxRM8AMYg5+1G0RQeXP8="; + + installPhase = '' + ls -lrth + + mkdir -p $out/bin $out/share/${pname} + install -Dm644 target/stream-examples.jar $out/share/${pname}/${pname}.jar + echo 'didier rocks!' + mkdir -p $out/bin $out/share/${pname} + makeWrapper ${pkgs.jdk22}/bin/java $out/bin/${pname} \ + --add-flags "-jar $out/share/${pname}/${pname}.jar" + ''; + + }; + in + { + packages = { + benchmark = benchmark; + }; + devShell = pkgs.mkShell { + buildInputs = with pkgs; [ + jdk22 + maven + ]; + }; + } + ); +} diff --git a/pom.xml b/pom.xml index 640de10..53bd9bb 100644 --- a/pom.xml +++ b/pom.xml @@ -4,9 +4,9 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - org.example + org.all-dressed-programming stream-examples - 1.0-SNAPSHOT + 0.1.0-SNAPSHOT 22 @@ -27,4 +27,38 @@ + + + + org.apache.maven.plugins + maven-help-plugin + 3.5.0 + + + org.apache.maven.plugins + maven-shade-plugin + 3.6.0 + + + package + + shade + + + ${project.artifactId} + + + + com.alldressedprogramming.Main + 1 + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/alldressedprogramming/Main.java b/src/main/java/com/alldressedprogramming/Main.java index db4a75b..4c5c865 100644 --- a/src/main/java/com/alldressedprogramming/Main.java +++ b/src/main/java/com/alldressedprogramming/Main.java @@ -1,5 +1,6 @@ package com.alldressedprogramming; +import java.util.concurrent.TimeUnit; import org.openjdk.jmh.annotations.*; import org.openjdk.jmh.infra.Blackhole; @@ -11,7 +12,12 @@ import java.util.stream.LongStream; import java.util.stream.Stream; -@State(Scope.Benchmark) +@State(Scope.Thread) +@Fork( 1 ) +@Warmup( iterations = 2 ) +@Measurement( iterations = 10 ) +@BenchmarkMode( Mode.AverageTime ) +@OutputTimeUnit( TimeUnit.MICROSECONDS ) public class Main { public record Song(List composers) { @@ -30,7 +36,6 @@ public class Main { } public static Album createFakeAlbum(Random random) { - var seed = random.nextLong(); var songs = IntStream.range(2, 25) .mapToObj(Random::new) .map(Main::createFakeSong) @@ -43,16 +48,9 @@ public class Main { .mapToObj(Random::new) .map(Main::createFakeAlbum) .toList(); - - } - - List albums; - - @Setup(Level.Invocation) - public void setUp() { - albums = createFakeAlbums(1000); } + final List albums = createFakeAlbums(10_000); @Benchmark public void classical(Blackhole blackhole) { @@ -92,6 +90,15 @@ public class Main { return ret; } + @Benchmark + public void brokenDownWithMethodsWith10Duplicates(Blackhole blackhole) { + for(int i = 0; i < 10; i++){ + List recentAlbums = getRecentAlbums(albums); + List newTaylorSwift = getTaylorSwiftSongs(recentAlbums); + blackhole.consume(newTaylorSwift); + } + } + @Benchmark public void brokenDownWithMethods(Blackhole blackhole) { List recentAlbums = getRecentAlbums(albums); @@ -113,10 +120,17 @@ public class Main { public void brokenDownWithMethodsWithStreams(Blackhole blackhole) { Stream recentAlbums = getRecentAlbumsAsStream(albums.stream()); Stream newTaylorSwift = getTaylorSwiftSongsAsStream(recentAlbums); - blackhole.consume(newTaylorSwift); + blackhole.consume(newTaylorSwift.toList()); } public static void main(String[] args) throws Exception { org.openjdk.jmh.Main.main(args); +// var main = new Main(); +// var albums = Main.createFakeAlbums(100); +// List recentAlbums = main.getRecentAlbums(albums); +// List newTaylorSwift = main.getTaylorSwiftSongs(recentAlbums); +// System.out.println(newTaylorSwift.size()); + } + } \ No newline at end of file diff --git a/src/main/java/com/alldressedprogramming/StreamBenchmarks.java b/src/main/java/com/alldressedprogramming/StreamBenchmarks.java new file mode 100644 index 0000000..308171f --- /dev/null +++ b/src/main/java/com/alldressedprogramming/StreamBenchmarks.java @@ -0,0 +1,114 @@ +package com.alldressedprogramming; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.ArrayList; +import java.util.concurrent.TimeUnit; +import java.util.stream.Stream; + +@Fork( 1 ) +@Warmup( iterations = 2 ) +@Measurement( iterations = 10 ) +@BenchmarkMode( Mode.AverageTime ) +@OutputTimeUnit( TimeUnit.MILLISECONDS ) +public class StreamBenchmarks +{ + + private static final int LIMIT = 10_000; + + enum Foo + { + ONE( 1 ), TWO( 2 ), THREE( 3 ), FOUR( 4 ), FIVE( 5 ), SIX( 6 ), SEVEN( 7 ), EIGHT( 8 ); + + private final int value; + + Foo( int value ) + { + this.value = value; + } + + public int getValue() + { + return value; + } + } + + @Benchmark + public void iterationWithForLoop( Blackhole blackhole ) + { + for ( int i = 0; i < LIMIT; i++ ) + { + var ret = new ArrayList(); + for ( var foo : Foo.values() ) + { + if ( foo.getValue() % 2 == 0 ) + { + ret.add( foo.getValue() ); + } + } + blackhole.consume( ret ); + } + + } + + @Benchmark + public void iterationWithStream( Blackhole blackhole ) + { + for ( int i = 0; i < LIMIT; i++ ) + { + var ret = Stream.of( Foo.values() ) + .map( Foo::getValue ) + .filter( x -> x % 2 == 0 ) + .toList(); + blackhole.consume( ret ); + } + + } + + @Benchmark + public void findFirstWithForLoop( Blackhole blackhole ) + { + for ( int i = 0; i < LIMIT; i++ ) + { + int ret = -1; + for ( var foo : Foo.values() ) + { + if ( foo.getValue() == 6 ) + { + break; + } + } + blackhole.consume( ret ); + + } + + } + + @Benchmark + public void findFirstWithStream( Blackhole blackhole ) + { + for ( int i = 0; i < LIMIT; i++ ) + { + var ret = Stream.of( Foo.values() ) + .map( Foo::getValue ) + .filter( x -> x == 6 ) + .findFirst() + .orElse( -1 ); + blackhole.consume( ret ); + } + + } + + public static void main( String[] args ) + throws Exception + { + org.openjdk.jmh.Main.main( args ); + } +} \ No newline at end of file