From 7b6ca611f69afe6bb948bc5a813d2b9381360ae4 Mon Sep 17 00:00:00 2001 From: Tom Tzook Date: Fri, 15 Nov 2019 19:50:40 +0200 Subject: [PATCH 01/21] added some benchmarking --- flashlibj/build.gradle | 29 +++++ .../flash3388/flashlib/robot/PlaceHolder.java | 5 + .../scheduling/SingleThreadSchedulerTest.java | 115 ++++++++++++++++++ 3 files changed, 149 insertions(+) create mode 100644 flashlibj/src/jmh/java/com/flash3388/flashlib/robot/PlaceHolder.java create mode 100644 flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/SingleThreadSchedulerTest.java diff --git a/flashlibj/build.gradle b/flashlibj/build.gradle index 53b3de2e6..d93d092fe 100644 --- a/flashlibj/build.gradle +++ b/flashlibj/build.gradle @@ -1,5 +1,34 @@ +plugins { + id "me.champeau.gradle.jmh" version "0.4.7" +} + apply from: rootProject.file('jcomponent.gradle') dependencies { compile project(':flashutil') +} + +jmh { + iterations = 10 // Number of measurement iterations to do. + batchSize = 1 // Batch size: number of benchmark method calls per operation. (some benchmark modes can ignore this setting) + fork = 2 // How many times to forks a single benchmark. Use 0 to disable forking altogether + failOnError = false // Should JMH fail immediately if any benchmark had experienced the unrecoverable error? + forceGC = false // Should JMH force GC between iterations? + humanOutputFile = project.file("${project.buildDir}/reports/jmh/human.txt") // human-readable output file + resultsFile = project.file("${project.buildDir}/reports/jmh/results.txt") // results file + benchmarkParameters = [:] // Benchmark parameters. + profilers = [] // Use profilers to collect additional data. Supported profilers: [cl, comp, gc, stack, perf, perfnorm, perfasm, xperf, xperfasm, hs_cl, hs_comp, hs_gc, hs_rt, hs_thr] + resultFormat = 'CSV' // Result format type (one of CSV, JSON, NONE, SCSV, TEXT) + synchronizeIterations = false // Synchronize iterations? + threads = 4 // Number of worker threads to run with. + timeUnit = 'ms' // Output time unit. Available time units are: [m, s, ms, us, ns]. + verbosity = 'NORMAL' // Verbosity mode. Available modes are: [SILENT, NORMAL, EXTRA] + warmup = '10s' // Time to spend at each warmup iteration. + warmupBatchSize = 10 // Warmup batch size: number of benchmark method calls per operation. + warmupForks = 0 // How many warmup forks to make for a single benchmark. 0 to disable warmup forks. + warmupIterations = 1 // Number of warmup iterations to do. + warmupMode = 'INDI' // Warmup mode for warming up selected benchmarks. Warmup modes are: [INDI, BULK, BULK_INDI]. + warmupBenchmarks = ['.*Warmup'] // Warmup benchmarks to include in the run in addition to already selected. JMH will not measure these benchmarks, but only use them for the warmup. + + jmhVersion = '1.21' // Specifies JMH version } \ No newline at end of file diff --git a/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/PlaceHolder.java b/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/PlaceHolder.java new file mode 100644 index 000000000..1316258ec --- /dev/null +++ b/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/PlaceHolder.java @@ -0,0 +1,5 @@ +package com.flash3388.flashlib.robot; + +public class PlaceHolder { + +} diff --git a/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/SingleThreadSchedulerTest.java b/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/SingleThreadSchedulerTest.java new file mode 100644 index 000000000..5f693f082 --- /dev/null +++ b/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/SingleThreadSchedulerTest.java @@ -0,0 +1,115 @@ +package com.flash3388.flashlib.robot.scheduling; + +import com.beans.Property; +import com.beans.properties.SimpleProperty; +import com.flash3388.flashlib.robot.modes.RobotMode; +import com.flash3388.flashlib.robot.scheduling.actions.Action; +import com.flash3388.flashlib.time.Clock; +import com.flash3388.flashlib.time.SystemNanoClock; +import com.flash3388.flashlib.time.Time; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.Random; +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.stream.IntStream; + +public class SingleThreadSchedulerTest { + + private static final RobotMode ROBOT_MODE = new RobotMode("test", 1); + + @State(value = Scope.Thread) + public static class SchedulerContext { + + private final Property mBlackholeProperty; + + @Param({"10", "30"}) + private int mActionsCount; + @Param({"SMALL"}) + private ActionSize mActionSize; + + private Scheduler mScheduler; + + public SchedulerContext() { + mBlackholeProperty = new SimpleProperty<>(); + } + + public Scheduler getScheduler() { + return mScheduler; + } + + public void setBlackhole(Blackhole blackhole) { + mBlackholeProperty.set(blackhole); + } + + @Setup(Level.Invocation) + public void prepare() { + Clock clock = new SystemNanoClock(); + mScheduler = new SingleThreadScheduler(clock); + + Consumer consumer = (object) -> { + Blackhole blackhole = mBlackholeProperty.get(); + blackhole.consume(object); + }; + + IntStream.range(0, mActionsCount) + .mapToObj((i) -> mActionSize.generate(mScheduler, consumer)) + .forEach(Action::start); + } + } + + @Benchmark + @BenchmarkMode(Mode.Throughput) + public void run_withSpecificLoad_iterationThroughput(SchedulerContext context, Blackhole blackhole) throws Exception { + context.setBlackhole(blackhole); + + Scheduler scheduler = context.getScheduler(); + scheduler.run(ROBOT_MODE); + } + + public enum ActionSize { + SMALL(SmallSizeAction::new) + ; + + private final BiFunction, Action> mActionGenerator; + + ActionSize(BiFunction, Action> actionGenerator) { + mActionGenerator = actionGenerator; + } + + Action generate(Scheduler scheduler, Consumer outputConsumer) { + return mActionGenerator.apply(scheduler, outputConsumer); + } + } + + private static class SmallSizeAction extends Action { + + private final Consumer mOutputConsumer; + private final Random mRandom; + + private SmallSizeAction(Scheduler scheduler, Consumer outputConsumer) { + super(scheduler, Time.INVALID); + mOutputConsumer = outputConsumer; + mRandom = new Random(); + } + + @Override + protected void execute() { + byte[] bytes = new byte[1024]; + mRandom.nextBytes(bytes); + + mOutputConsumer.accept(bytes); + } + + @Override + protected void end() { } + } +} From c64e55f9bfe098b9b1fb50559a988426052f4996 Mon Sep 17 00:00:00 2001 From: Tom Tzook Date: Fri, 15 Nov 2019 21:29:02 +0200 Subject: [PATCH 02/21] expanding on scheduler benchmark --- .../benchmark/util/GlobalRandom.java | 12 +++ .../java/benchmark/benchmark/util/Range.java | 20 ++++ ...dulerTest.java => SchedulerBenchmark.java} | 102 ++++++++++++++---- .../robot/scheduling/actions/Action.java | 4 + .../actions/ParallelActionGroup.java | 8 +- .../actions/SequentialActionGroup.java | 9 +- 6 files changed, 132 insertions(+), 23 deletions(-) create mode 100644 flashlibj/src/jmh/java/benchmark/benchmark/util/GlobalRandom.java create mode 100644 flashlibj/src/jmh/java/benchmark/benchmark/util/Range.java rename flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/{SingleThreadSchedulerTest.java => SchedulerBenchmark.java} (50%) diff --git a/flashlibj/src/jmh/java/benchmark/benchmark/util/GlobalRandom.java b/flashlibj/src/jmh/java/benchmark/benchmark/util/GlobalRandom.java new file mode 100644 index 000000000..441e644e3 --- /dev/null +++ b/flashlibj/src/jmh/java/benchmark/benchmark/util/GlobalRandom.java @@ -0,0 +1,12 @@ +package benchmark.benchmark.util; + +import java.util.Random; + +public class GlobalRandom { + + private static final Random RANDOM = new Random(); + + public static int nextIntInRange(Range range) { + return RANDOM.nextInt(range.getMax() + range.getMin()) - range.getMin(); + } +} diff --git a/flashlibj/src/jmh/java/benchmark/benchmark/util/Range.java b/flashlibj/src/jmh/java/benchmark/benchmark/util/Range.java new file mode 100644 index 000000000..266798c3f --- /dev/null +++ b/flashlibj/src/jmh/java/benchmark/benchmark/util/Range.java @@ -0,0 +1,20 @@ +package benchmark.benchmark.util; + +public class Range { + + private final int mMin; + private final int mMax; + + public Range(int min, int max) { + mMin = min; + mMax = max; + } + + public int getMin() { + return mMin; + } + + public int getMax() { + return mMax; + } +} diff --git a/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/SingleThreadSchedulerTest.java b/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/SchedulerBenchmark.java similarity index 50% rename from flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/SingleThreadSchedulerTest.java rename to flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/SchedulerBenchmark.java index 5f693f082..f9d2e10ba 100644 --- a/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/SingleThreadSchedulerTest.java +++ b/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/SchedulerBenchmark.java @@ -1,10 +1,12 @@ package com.flash3388.flashlib.robot.scheduling; +import benchmark.benchmark.util.GlobalRandom; +import benchmark.benchmark.util.Range; import com.beans.Property; import com.beans.properties.SimpleProperty; import com.flash3388.flashlib.robot.modes.RobotMode; import com.flash3388.flashlib.robot.scheduling.actions.Action; -import com.flash3388.flashlib.time.Clock; +import com.flash3388.flashlib.robot.scheduling.actions.SequentialActionGroup; import com.flash3388.flashlib.time.SystemNanoClock; import com.flash3388.flashlib.time.Time; import org.openjdk.jmh.annotations.Benchmark; @@ -17,31 +19,41 @@ import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.infra.Blackhole; +import java.util.Collection; import java.util.Random; import java.util.function.BiFunction; import java.util.function.Consumer; +import java.util.function.Supplier; +import java.util.stream.Collectors; import java.util.stream.IntStream; -public class SingleThreadSchedulerTest { +public class SchedulerBenchmark { private static final RobotMode ROBOT_MODE = new RobotMode("test", 1); + @Benchmark + @BenchmarkMode(Mode.Throughput) + public void run_withSpecificLoad_iterationThroughput(SchedulerContext context, Blackhole blackhole) throws Exception { + context.setBlackhole(blackhole); + + Scheduler scheduler = context.getScheduler(); + scheduler.run(ROBOT_MODE); + } + @State(value = Scope.Thread) public static class SchedulerContext { - private final Property mBlackholeProperty; + private final Property mBlackholeProperty = new SimpleProperty<>(); @Param({"10", "30"}) private int mActionsCount; - @Param({"SMALL"}) - private ActionSize mActionSize; + @Param({"SMALL", "MEDIUM", "SMALL_SINGLE_SEQ_GROUP", "SMALL_MULTI_SEQ_GROUP"}) + private ActionType mActionType; + @Param({"SINGLE_THREAD"}) + private SchedulerImpl mSchedulerImpl; private Scheduler mScheduler; - public SchedulerContext() { - mBlackholeProperty = new SimpleProperty<>(); - } - public Scheduler getScheduler() { return mScheduler; } @@ -52,8 +64,7 @@ public void setBlackhole(Blackhole blackhole) { @Setup(Level.Invocation) public void prepare() { - Clock clock = new SystemNanoClock(); - mScheduler = new SingleThreadScheduler(clock); + mScheduler = mSchedulerImpl.generate(); Consumer consumer = (object) -> { Blackhole blackhole = mBlackholeProperty.get(); @@ -61,27 +72,38 @@ public void prepare() { }; IntStream.range(0, mActionsCount) - .mapToObj((i) -> mActionSize.generate(mScheduler, consumer)) + .mapToObj((i) -> mActionType.generate(mScheduler, consumer)) .forEach(Action::start); } } - @Benchmark - @BenchmarkMode(Mode.Throughput) - public void run_withSpecificLoad_iterationThroughput(SchedulerContext context, Blackhole blackhole) throws Exception { - context.setBlackhole(blackhole); + public enum SchedulerImpl { + SINGLE_THREAD(()->new SingleThreadScheduler(new SystemNanoClock())) + ; - Scheduler scheduler = context.getScheduler(); - scheduler.run(ROBOT_MODE); + private final Supplier mGenerator; + + SchedulerImpl(Supplier generator) { + mGenerator = generator; + } + + Scheduler generate() { + return mGenerator.get(); + } } - public enum ActionSize { - SMALL(SmallSizeAction::new) + public enum ActionType { + SMALL(SmallSizeAction::new), + MEDIUM(MediumSizeAction::new), + SMALL_SINGLE_SEQ_GROUP((scheduler, outputConsumer)-> + new GenericSequentialActionGroup(ActionType.SMALL, new Range(1, 1), scheduler, outputConsumer)), + SMALL_MULTI_SEQ_GROUP((scheduler, outputConsumer)-> + new GenericSequentialActionGroup(ActionType.SMALL, new Range(2, 3), scheduler, outputConsumer)) ; private final BiFunction, Action> mActionGenerator; - ActionSize(BiFunction, Action> actionGenerator) { + ActionType(BiFunction, Action> actionGenerator) { mActionGenerator = actionGenerator; } @@ -112,4 +134,42 @@ protected void execute() { @Override protected void end() { } } + + private static class MediumSizeAction extends Action { + + private final Consumer mOutputConsumer; + private final Random mRandom; + + private MediumSizeAction(Scheduler scheduler, Consumer outputConsumer) { + super(scheduler, Time.INVALID); + mOutputConsumer = outputConsumer; + mRandom = new Random(); + } + + @Override + protected void execute() { + Collection numbers = IntStream.range(0, 100) + .mapToObj((i) -> mRandom.nextInt()) + .sorted(Integer::compareTo) + .collect(Collectors.toList()); + + mOutputConsumer.accept(numbers); + } + + @Override + protected void end() { } + } + + private static class GenericSequentialActionGroup extends SequentialActionGroup { + + private GenericSequentialActionGroup(ActionType containedType, Range amountRange, + Scheduler scheduler, Consumer outputConsumer) { + super(scheduler, new SystemNanoClock()); + + int actionsCount = GlobalRandom.nextIntInRange(amountRange); + IntStream.range(0, actionsCount) + .forEach((i)->add(containedType.generate(scheduler, outputConsumer))); + + } + } } diff --git a/flashlibj/src/main/java/com/flash3388/flashlib/robot/scheduling/actions/Action.java b/flashlibj/src/main/java/com/flash3388/flashlib/robot/scheduling/actions/Action.java index 76f4a492e..e49a0f6a7 100644 --- a/flashlibj/src/main/java/com/flash3388/flashlib/robot/scheduling/actions/Action.java +++ b/flashlibj/src/main/java/com/flash3388/flashlib/robot/scheduling/actions/Action.java @@ -66,6 +66,10 @@ public Action(Scheduler scheduler, Time timeout) { mParent = null; } + public Action(Scheduler scheduler) { + this(scheduler, Time.INVALID); + } + public Action(Time timeout) { this(RunningRobot.INSTANCE.get().getScheduler(), timeout); } diff --git a/flashlibj/src/main/java/com/flash3388/flashlib/robot/scheduling/actions/ParallelActionGroup.java b/flashlibj/src/main/java/com/flash3388/flashlib/robot/scheduling/actions/ParallelActionGroup.java index 3e01a29cb..6481eda0b 100644 --- a/flashlibj/src/main/java/com/flash3388/flashlib/robot/scheduling/actions/ParallelActionGroup.java +++ b/flashlibj/src/main/java/com/flash3388/flashlib/robot/scheduling/actions/ParallelActionGroup.java @@ -1,6 +1,7 @@ package com.flash3388.flashlib.robot.scheduling.actions; import com.flash3388.flashlib.robot.RunningRobot; +import com.flash3388.flashlib.robot.scheduling.Scheduler; import com.flash3388.flashlib.time.Clock; import java.util.ArrayList; @@ -18,7 +19,8 @@ public class ParallelActionGroup extends Action { private boolean mRunWhenDisabled; - public ParallelActionGroup(Clock clock) { + public ParallelActionGroup(Scheduler scheduler, Clock clock) { + super(scheduler); mClock = clock; mActions = new ArrayList<>(3); @@ -27,6 +29,10 @@ public ParallelActionGroup(Clock clock) { mRunWhenDisabled = false; } + public ParallelActionGroup(Clock clock) { + this(RunningRobot.INSTANCE.get().getScheduler(), clock); + } + public ParallelActionGroup() { this(RunningRobot.INSTANCE.get().getClock()); } diff --git a/flashlibj/src/main/java/com/flash3388/flashlib/robot/scheduling/actions/SequentialActionGroup.java b/flashlibj/src/main/java/com/flash3388/flashlib/robot/scheduling/actions/SequentialActionGroup.java index d00f244bc..9c3fd2733 100644 --- a/flashlibj/src/main/java/com/flash3388/flashlib/robot/scheduling/actions/SequentialActionGroup.java +++ b/flashlibj/src/main/java/com/flash3388/flashlib/robot/scheduling/actions/SequentialActionGroup.java @@ -1,7 +1,9 @@ package com.flash3388.flashlib.robot.scheduling.actions; import com.flash3388.flashlib.robot.RunningRobot; +import com.flash3388.flashlib.robot.scheduling.Scheduler; import com.flash3388.flashlib.time.Clock; +import com.flash3388.flashlib.time.Time; import java.util.ArrayDeque; import java.util.ArrayList; @@ -20,7 +22,8 @@ public class SequentialActionGroup extends Action { private ActionContext mCurrentAction; private boolean mRunWhenDisabled; - public SequentialActionGroup(Clock clock) { + public SequentialActionGroup(Scheduler scheduler, Clock clock) { + super(scheduler); mClock = clock; mActions = new ArrayList<>(3); @@ -30,6 +33,10 @@ public SequentialActionGroup(Clock clock) { mRunWhenDisabled = false; } + public SequentialActionGroup(Clock clock) { + this(RunningRobot.INSTANCE.get().getScheduler(), clock); + } + public SequentialActionGroup() { this(RunningRobot.INSTANCE.get().getClock()); } From e949228e2472ab9c4e1e8f30e95fd20377f6b84c Mon Sep 17 00:00:00 2001 From: Tom Tzook Date: Sat, 16 Nov 2019 10:52:32 +0200 Subject: [PATCH 03/21] working on better benchmarks --- build.gradle | 14 ++ component-benchmark.gradle | 45 ++++++ flashlibj/build.gradle | 30 +--- .../benchmark/util/GlobalRandom.java | 2 +- .../flash3388/flashlib/robot/PlaceHolder.java | 5 - .../robot/scheduling/EmptyScheduler.java | 40 +++++ .../robot/scheduling/SchedulerBenchmark.java | 153 ++++-------------- .../scheduling/actions/ActionsBenchmark.java | 48 ++++++ .../robot/scheduling/actions/TestActions.java | 120 ++++++++++++++ 9 files changed, 296 insertions(+), 161 deletions(-) create mode 100644 component-benchmark.gradle delete mode 100644 flashlibj/src/jmh/java/com/flash3388/flashlib/robot/PlaceHolder.java create mode 100644 flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/EmptyScheduler.java create mode 100644 flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/actions/ActionsBenchmark.java create mode 100644 flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/actions/TestActions.java diff --git a/build.gradle b/build.gradle index 49614dd1a..56c8a859b 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,19 @@ apply plugin: 'signing' +buildscript { + + repositories { + jcenter() + maven { + url "https://plugins.gradle.org/m2/" + } + } + + dependencies { + classpath "me.champeau.gradle:jmh-gradle-plugin:0.4.7" + } +} + allprojects { group = GROUP version = VERSION diff --git a/component-benchmark.gradle b/component-benchmark.gradle new file mode 100644 index 000000000..e893c0fd3 --- /dev/null +++ b/component-benchmark.gradle @@ -0,0 +1,45 @@ +apply plugin: "me.champeau.gradle.jmh" + +ext { + BENCHMARK_RESULTS_DIR = project.file("${project.buildDir}/reports/jmh") + BENCHMARK_OUTPUT_DIRS = [ + project.file("${project.buildDir}/jmh-generated-classes"), + project.file("${project.buildDir}/jmh-generated-resources"), + project.file("${project.buildDir}/jmh-generated-sources") + ] +} + +jmh { + iterations = 10 // Number of measurement iterations to do. + batchSize = 1 // Batch size: number of benchmark method calls per operation. (some benchmark modes can ignore this setting) + fork = 2 // How many times to forks a single benchmark. Use 0 to disable forking altogether + failOnError = false // Should JMH fail immediately if any benchmark had experienced the unrecoverable error? + forceGC = false // Should JMH force GC between iterations? + humanOutputFile = new File(BENCHMARK_RESULTS_DIR, "human.txt") // human-readable output file + resultsFile = new File(BENCHMARK_RESULTS_DIR, "results.txt") // results file + benchmarkParameters = [:] // Benchmark parameters. + profilers = ['gc', 'stack'] // Use profilers to collect additional data. Supported profilers: [cl, comp, gc, stack, perf, perfnorm, perfasm, xperf, xperfasm, hs_cl, hs_comp, hs_gc, hs_rt, hs_thr] + resultFormat = 'JSON' // Result format type (one of CSV, JSON, NONE, SCSV, TEXT) + synchronizeIterations = false // Synchronize iterations? + threads = 4 // Number of worker threads to run with. + timeUnit = 'ms' // Output time unit. Available time units are: [m, s, ms, us, ns]. + verbosity = 'NORMAL' // Verbosity mode. Available modes are: [SILENT, NORMAL, EXTRA] + warmup = '10s' // Time to spend at each warmup iteration. + warmupBatchSize = 10 // Warmup batch size: number of benchmark method calls per operation. + warmupForks = 0 // How many warmup forks to make for a single benchmark. 0 to disable warmup forks. + warmupIterations = 1 // Number of warmup iterations to do. + warmupMode = 'INDI' // Warmup mode for warming up selected benchmarks. Warmup modes are: [INDI, BULK, BULK_INDI]. + warmupBenchmarks = ['.*Warmup'] // Warmup benchmarks to include in the run in addition to already selected. JMH will not measure these benchmarks, but only use them for the warmup. + + jmhVersion = '1.21' // Specifies JMH version +} + +task clearBenchmarkResults(type: Delete) { + BENCHMARK_OUTPUT_DIRS.each { + delete it + } +} + +task benchmark { + dependsOn clearBenchmarkResults, jmh +} diff --git a/flashlibj/build.gradle b/flashlibj/build.gradle index d93d092fe..984185ef0 100644 --- a/flashlibj/build.gradle +++ b/flashlibj/build.gradle @@ -1,34 +1,6 @@ -plugins { - id "me.champeau.gradle.jmh" version "0.4.7" -} - apply from: rootProject.file('jcomponent.gradle') +apply from: rootProject.file('component-benchmark.gradle') dependencies { compile project(':flashutil') } - -jmh { - iterations = 10 // Number of measurement iterations to do. - batchSize = 1 // Batch size: number of benchmark method calls per operation. (some benchmark modes can ignore this setting) - fork = 2 // How many times to forks a single benchmark. Use 0 to disable forking altogether - failOnError = false // Should JMH fail immediately if any benchmark had experienced the unrecoverable error? - forceGC = false // Should JMH force GC between iterations? - humanOutputFile = project.file("${project.buildDir}/reports/jmh/human.txt") // human-readable output file - resultsFile = project.file("${project.buildDir}/reports/jmh/results.txt") // results file - benchmarkParameters = [:] // Benchmark parameters. - profilers = [] // Use profilers to collect additional data. Supported profilers: [cl, comp, gc, stack, perf, perfnorm, perfasm, xperf, xperfasm, hs_cl, hs_comp, hs_gc, hs_rt, hs_thr] - resultFormat = 'CSV' // Result format type (one of CSV, JSON, NONE, SCSV, TEXT) - synchronizeIterations = false // Synchronize iterations? - threads = 4 // Number of worker threads to run with. - timeUnit = 'ms' // Output time unit. Available time units are: [m, s, ms, us, ns]. - verbosity = 'NORMAL' // Verbosity mode. Available modes are: [SILENT, NORMAL, EXTRA] - warmup = '10s' // Time to spend at each warmup iteration. - warmupBatchSize = 10 // Warmup batch size: number of benchmark method calls per operation. - warmupForks = 0 // How many warmup forks to make for a single benchmark. 0 to disable warmup forks. - warmupIterations = 1 // Number of warmup iterations to do. - warmupMode = 'INDI' // Warmup mode for warming up selected benchmarks. Warmup modes are: [INDI, BULK, BULK_INDI]. - warmupBenchmarks = ['.*Warmup'] // Warmup benchmarks to include in the run in addition to already selected. JMH will not measure these benchmarks, but only use them for the warmup. - - jmhVersion = '1.21' // Specifies JMH version -} \ No newline at end of file diff --git a/flashlibj/src/jmh/java/benchmark/benchmark/util/GlobalRandom.java b/flashlibj/src/jmh/java/benchmark/benchmark/util/GlobalRandom.java index 441e644e3..11fd5b7c3 100644 --- a/flashlibj/src/jmh/java/benchmark/benchmark/util/GlobalRandom.java +++ b/flashlibj/src/jmh/java/benchmark/benchmark/util/GlobalRandom.java @@ -7,6 +7,6 @@ public class GlobalRandom { private static final Random RANDOM = new Random(); public static int nextIntInRange(Range range) { - return RANDOM.nextInt(range.getMax() + range.getMin()) - range.getMin(); + return RANDOM.nextInt(range.getMax() - range.getMin() + 1) + range.getMin(); } } diff --git a/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/PlaceHolder.java b/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/PlaceHolder.java deleted file mode 100644 index 1316258ec..000000000 --- a/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/PlaceHolder.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.flash3388.flashlib.robot; - -public class PlaceHolder { - -} diff --git a/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/EmptyScheduler.java b/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/EmptyScheduler.java new file mode 100644 index 000000000..ce49287a4 --- /dev/null +++ b/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/EmptyScheduler.java @@ -0,0 +1,40 @@ +package com.flash3388.flashlib.robot.scheduling; + +import com.flash3388.flashlib.robot.modes.RobotMode; +import com.flash3388.flashlib.robot.scheduling.actions.Action; + +import java.util.Optional; +import java.util.function.Predicate; + +public class EmptyScheduler implements Scheduler { + + @Override + public void add(Action action) { + + } + + @Override + public void stopAllActions() { + + } + + @Override + public void stopActionsIf(Predicate removalPredicate) { + + } + + @Override + public void setDefaultAction(Subsystem subsystem, Action action) { + + } + + @Override + public Optional getActionRunningOnSubsystem(Subsystem subsystem) { + return Optional.empty(); + } + + @Override + public void run(RobotMode robotMode) { + + } +} diff --git a/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/SchedulerBenchmark.java b/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/SchedulerBenchmark.java index f9d2e10ba..3c214e202 100644 --- a/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/SchedulerBenchmark.java +++ b/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/SchedulerBenchmark.java @@ -1,14 +1,11 @@ package com.flash3388.flashlib.robot.scheduling; -import benchmark.benchmark.util.GlobalRandom; -import benchmark.benchmark.util.Range; import com.beans.Property; import com.beans.properties.SimpleProperty; import com.flash3388.flashlib.robot.modes.RobotMode; import com.flash3388.flashlib.robot.scheduling.actions.Action; -import com.flash3388.flashlib.robot.scheduling.actions.SequentialActionGroup; +import com.flash3388.flashlib.robot.scheduling.actions.TestActions; import com.flash3388.flashlib.time.SystemNanoClock; -import com.flash3388.flashlib.time.Time; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Level; @@ -19,62 +16,47 @@ import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.infra.Blackhole; -import java.util.Collection; -import java.util.Random; -import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Supplier; -import java.util.stream.Collectors; import java.util.stream.IntStream; +@State(Scope.Thread) public class SchedulerBenchmark { private static final RobotMode ROBOT_MODE = new RobotMode("test", 1); - @Benchmark - @BenchmarkMode(Mode.Throughput) - public void run_withSpecificLoad_iterationThroughput(SchedulerContext context, Blackhole blackhole) throws Exception { - context.setBlackhole(blackhole); - - Scheduler scheduler = context.getScheduler(); - scheduler.run(ROBOT_MODE); - } - - @State(value = Scope.Thread) - public static class SchedulerContext { + private Property mBlackholeProperty = new SimpleProperty<>(); - private final Property mBlackholeProperty = new SimpleProperty<>(); + @Param({"10", "30"}) + private int mActionsCount; + @Param({"SMALL", "MEDIUM", "SHORT_SLEEP", "SMALL_SINGLE_SEQ_GROUP", "SMALL_MULTI_SEQ_GROUP"}) + private TestActions.ActionType mActionType; + @Param({"SINGLE_THREAD"}) + private SchedulerImpl mSchedulerImpl; - @Param({"10", "30"}) - private int mActionsCount; - @Param({"SMALL", "MEDIUM", "SMALL_SINGLE_SEQ_GROUP", "SMALL_MULTI_SEQ_GROUP"}) - private ActionType mActionType; - @Param({"SINGLE_THREAD"}) - private SchedulerImpl mSchedulerImpl; + private Scheduler mScheduler; - private Scheduler mScheduler; + @Setup(Level.Trial) + public void setup() { + mScheduler = mSchedulerImpl.generate(); - public Scheduler getScheduler() { - return mScheduler; - } - - public void setBlackhole(Blackhole blackhole) { - mBlackholeProperty.set(blackhole); - } + Consumer consumer = (object) -> { + Blackhole blackhole = mBlackholeProperty.get(); + blackhole.consume(object); + }; - @Setup(Level.Invocation) - public void prepare() { - mScheduler = mSchedulerImpl.generate(); + IntStream.range(0, mActionsCount) + .mapToObj((i) -> mActionType.generate(mScheduler, consumer)) + .forEach(Action::start); + } - Consumer consumer = (object) -> { - Blackhole blackhole = mBlackholeProperty.get(); - blackhole.consume(object); - }; + @Benchmark + @BenchmarkMode(Mode.Throughput) + public void run_withSpecificLoad_iterationThroughput(Blackhole blackhole) throws Exception { + mBlackholeProperty.set(blackhole); - IntStream.range(0, mActionsCount) - .mapToObj((i) -> mActionType.generate(mScheduler, consumer)) - .forEach(Action::start); - } + Scheduler scheduler = mScheduler; + scheduler.run(ROBOT_MODE); } public enum SchedulerImpl { @@ -91,85 +73,4 @@ Scheduler generate() { return mGenerator.get(); } } - - public enum ActionType { - SMALL(SmallSizeAction::new), - MEDIUM(MediumSizeAction::new), - SMALL_SINGLE_SEQ_GROUP((scheduler, outputConsumer)-> - new GenericSequentialActionGroup(ActionType.SMALL, new Range(1, 1), scheduler, outputConsumer)), - SMALL_MULTI_SEQ_GROUP((scheduler, outputConsumer)-> - new GenericSequentialActionGroup(ActionType.SMALL, new Range(2, 3), scheduler, outputConsumer)) - ; - - private final BiFunction, Action> mActionGenerator; - - ActionType(BiFunction, Action> actionGenerator) { - mActionGenerator = actionGenerator; - } - - Action generate(Scheduler scheduler, Consumer outputConsumer) { - return mActionGenerator.apply(scheduler, outputConsumer); - } - } - - private static class SmallSizeAction extends Action { - - private final Consumer mOutputConsumer; - private final Random mRandom; - - private SmallSizeAction(Scheduler scheduler, Consumer outputConsumer) { - super(scheduler, Time.INVALID); - mOutputConsumer = outputConsumer; - mRandom = new Random(); - } - - @Override - protected void execute() { - byte[] bytes = new byte[1024]; - mRandom.nextBytes(bytes); - - mOutputConsumer.accept(bytes); - } - - @Override - protected void end() { } - } - - private static class MediumSizeAction extends Action { - - private final Consumer mOutputConsumer; - private final Random mRandom; - - private MediumSizeAction(Scheduler scheduler, Consumer outputConsumer) { - super(scheduler, Time.INVALID); - mOutputConsumer = outputConsumer; - mRandom = new Random(); - } - - @Override - protected void execute() { - Collection numbers = IntStream.range(0, 100) - .mapToObj((i) -> mRandom.nextInt()) - .sorted(Integer::compareTo) - .collect(Collectors.toList()); - - mOutputConsumer.accept(numbers); - } - - @Override - protected void end() { } - } - - private static class GenericSequentialActionGroup extends SequentialActionGroup { - - private GenericSequentialActionGroup(ActionType containedType, Range amountRange, - Scheduler scheduler, Consumer outputConsumer) { - super(scheduler, new SystemNanoClock()); - - int actionsCount = GlobalRandom.nextIntInRange(amountRange); - IntStream.range(0, actionsCount) - .forEach((i)->add(containedType.generate(scheduler, outputConsumer))); - - } - } } diff --git a/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/actions/ActionsBenchmark.java b/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/actions/ActionsBenchmark.java new file mode 100644 index 000000000..20dc64631 --- /dev/null +++ b/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/actions/ActionsBenchmark.java @@ -0,0 +1,48 @@ +package com.flash3388.flashlib.robot.scheduling.actions; + +import com.beans.Property; +import com.beans.properties.SimpleProperty; +import com.flash3388.flashlib.robot.scheduling.EmptyScheduler; +import com.flash3388.flashlib.robot.scheduling.Scheduler; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.function.Consumer; + +@State(Scope.Thread) +public class ActionsBenchmark { + + private Property mBlackholeProperty = new SimpleProperty<>(); + + @Param({"SMALL", "MEDIUM", "SHORT_SLEEP", "SMALL_SINGLE_SEQ_GROUP", "SMALL_MULTI_SEQ_GROUP"}) + private TestActions.ActionType mActionType; + + private Action mAction; + + @Setup(Level.Trial) + public void setup() { + Scheduler scheduler = new EmptyScheduler(); + + Consumer consumer = (object) -> { + Blackhole blackhole = mBlackholeProperty.get(); + blackhole.consume(object); + }; + + mAction = mActionType.generate(scheduler, consumer); + } + + @Benchmark + @BenchmarkMode({Mode.AverageTime, Mode.Throughput}) + public void execute_forTestAction(Blackhole blackhole) { + mBlackholeProperty.set(blackhole); + + mAction.execute(); + } +} diff --git a/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/actions/TestActions.java b/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/actions/TestActions.java new file mode 100644 index 000000000..1affb603e --- /dev/null +++ b/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/actions/TestActions.java @@ -0,0 +1,120 @@ +package com.flash3388.flashlib.robot.scheduling.actions; + +import benchmark.benchmark.util.GlobalRandom; +import benchmark.benchmark.util.Range; +import com.flash3388.flashlib.robot.scheduling.Scheduler; +import com.flash3388.flashlib.time.SystemNanoClock; +import com.flash3388.flashlib.time.Time; + +import java.util.Collection; +import java.util.Random; +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public class TestActions { + + public enum ActionType { + SMALL(SmallSizeAction::new), + MEDIUM(MediumSizeAction::new), + SHORT_SLEEP((scheduler, outputConsumer)-> + new SleepingAction(scheduler, 1L)), + SMALL_SINGLE_SEQ_GROUP((scheduler, outputConsumer)-> + new GenericSequentialActionGroup(ActionType.SMALL, new Range(1, 1), scheduler, outputConsumer)), + SMALL_MULTI_SEQ_GROUP((scheduler, outputConsumer)-> + new GenericSequentialActionGroup(ActionType.SMALL, new Range(2, 3), scheduler, outputConsumer)) + ; + + private final BiFunction, Action> mActionGenerator; + + ActionType(BiFunction, Action> actionGenerator) { + mActionGenerator = actionGenerator; + } + + public Action generate(Scheduler scheduler, Consumer outputConsumer) { + return mActionGenerator.apply(scheduler, outputConsumer); + } + } + + public static class SmallSizeAction extends Action { + + private final Consumer mOutputConsumer; + private final Random mRandom; + + private SmallSizeAction(Scheduler scheduler, Consumer outputConsumer) { + super(scheduler, Time.INVALID); + mOutputConsumer = outputConsumer; + mRandom = new Random(); + } + + @Override + protected void execute() { + byte[] bytes = new byte[1024]; + mRandom.nextBytes(bytes); + + mOutputConsumer.accept(bytes); + } + + @Override + protected void end() { } + } + + public static class MediumSizeAction extends Action { + + private final Consumer mOutputConsumer; + private final Random mRandom; + + private MediumSizeAction(Scheduler scheduler, Consumer outputConsumer) { + super(scheduler, Time.INVALID); + mOutputConsumer = outputConsumer; + mRandom = new Random(); + } + + @Override + protected void execute() { + Collection numbers = IntStream.range(0, 100) + .mapToObj((i) -> mRandom.nextInt()) + .sorted(Integer::compareTo) + .collect(Collectors.toList()); + + mOutputConsumer.accept(numbers); + } + + @Override + protected void end() { } + } + + public static class SleepingAction extends Action { + + private final long mSleepTimeMs; + + private SleepingAction(Scheduler scheduler, long sleepTimeMs) { + super(scheduler); + mSleepTimeMs = sleepTimeMs; + } + + @Override + protected void execute() { + try { + Thread.sleep(mSleepTimeMs); + } catch (InterruptedException e) { } + } + + @Override + protected void end() { } + } + + public static class GenericSequentialActionGroup extends SequentialActionGroup { + + private GenericSequentialActionGroup(ActionType containedType, Range amountRange, + Scheduler scheduler, Consumer outputConsumer) { + super(scheduler, new SystemNanoClock()); + + int actionsCount = GlobalRandom.nextIntInRange(amountRange); + IntStream.range(0, actionsCount) + .forEach((i)->add(containedType.generate(scheduler, outputConsumer))); + + } + } +} From cc3b14787436b41ac21084c97daf3d9697226bef Mon Sep 17 00:00:00 2001 From: Tom Tzook Date: Sat, 16 Nov 2019 12:45:06 +0200 Subject: [PATCH 04/21] continuing benchmark organization --- ....java => SchedulerExecutionBenchmark.java} | 24 ++----- .../robot/scheduling/SchedulerImpl.java | 20 ++++++ .../scheduling/actions/ActionsBenchmark.java | 3 +- .../robot/scheduling/actions/TestAction.java | 17 +++++ .../scheduling/actions/TestActionParams.java | 24 +++++++ .../robot/scheduling/actions/TestActions.java | 64 +++++++++---------- .../actions/TestSequentialActionGroup.java | 19 ++++++ 7 files changed, 115 insertions(+), 56 deletions(-) rename flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/{SchedulerBenchmark.java => SchedulerExecutionBenchmark.java} (75%) create mode 100644 flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/SchedulerImpl.java create mode 100644 flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/actions/TestAction.java create mode 100644 flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/actions/TestActionParams.java create mode 100644 flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/actions/TestSequentialActionGroup.java diff --git a/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/SchedulerBenchmark.java b/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/SchedulerExecutionBenchmark.java similarity index 75% rename from flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/SchedulerBenchmark.java rename to flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/SchedulerExecutionBenchmark.java index 3c214e202..2088ab890 100644 --- a/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/SchedulerBenchmark.java +++ b/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/SchedulerExecutionBenchmark.java @@ -4,8 +4,8 @@ import com.beans.properties.SimpleProperty; import com.flash3388.flashlib.robot.modes.RobotMode; import com.flash3388.flashlib.robot.scheduling.actions.Action; +import com.flash3388.flashlib.robot.scheduling.actions.TestActionParams; import com.flash3388.flashlib.robot.scheduling.actions.TestActions; -import com.flash3388.flashlib.time.SystemNanoClock; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Level; @@ -17,11 +17,10 @@ import org.openjdk.jmh.infra.Blackhole; import java.util.function.Consumer; -import java.util.function.Supplier; import java.util.stream.IntStream; @State(Scope.Thread) -public class SchedulerBenchmark { +public class SchedulerExecutionBenchmark { private static final RobotMode ROBOT_MODE = new RobotMode("test", 1); @@ -38,7 +37,7 @@ public class SchedulerBenchmark { @Setup(Level.Trial) public void setup() { - mScheduler = mSchedulerImpl.generate(); + mScheduler = mSchedulerImpl.create(); Consumer consumer = (object) -> { Blackhole blackhole = mBlackholeProperty.get(); @@ -46,7 +45,7 @@ public void setup() { }; IntStream.range(0, mActionsCount) - .mapToObj((i) -> mActionType.generate(mScheduler, consumer)) + .mapToObj((i) -> mActionType.create(new TestActionParams(mScheduler, consumer))) .forEach(Action::start); } @@ -58,19 +57,4 @@ public void run_withSpecificLoad_iterationThroughput(Blackhole blackhole) throws Scheduler scheduler = mScheduler; scheduler.run(ROBOT_MODE); } - - public enum SchedulerImpl { - SINGLE_THREAD(()->new SingleThreadScheduler(new SystemNanoClock())) - ; - - private final Supplier mGenerator; - - SchedulerImpl(Supplier generator) { - mGenerator = generator; - } - - Scheduler generate() { - return mGenerator.get(); - } - } } diff --git a/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/SchedulerImpl.java b/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/SchedulerImpl.java new file mode 100644 index 000000000..fa3827c37 --- /dev/null +++ b/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/SchedulerImpl.java @@ -0,0 +1,20 @@ +package com.flash3388.flashlib.robot.scheduling; + +import com.flash3388.flashlib.time.SystemNanoClock; + +import java.util.function.Supplier; + +public enum SchedulerImpl { + SINGLE_THREAD(()->new SingleThreadScheduler(new SystemNanoClock())) + ; + + private final Supplier mGenerator; + + SchedulerImpl(Supplier generator) { + mGenerator = generator; + } + + public Scheduler create() { + return mGenerator.get(); + } +} diff --git a/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/actions/ActionsBenchmark.java b/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/actions/ActionsBenchmark.java index 20dc64631..d23fb9086 100644 --- a/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/actions/ActionsBenchmark.java +++ b/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/actions/ActionsBenchmark.java @@ -35,7 +35,8 @@ public void setup() { blackhole.consume(object); }; - mAction = mActionType.generate(scheduler, consumer); + mAction = mActionType.create(new TestActionParams(scheduler, consumer)); + mAction.initialize(); } @Benchmark diff --git a/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/actions/TestAction.java b/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/actions/TestAction.java new file mode 100644 index 000000000..a1602840a --- /dev/null +++ b/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/actions/TestAction.java @@ -0,0 +1,17 @@ +package com.flash3388.flashlib.robot.scheduling.actions; + +import java.util.function.Consumer; + +public abstract class TestAction extends Action { + + private final Consumer mOutputConsumer; + + public TestAction(TestActionParams params) { + super(params.getScheduler()); + mOutputConsumer = params.getOutputConsumer(); + } + + protected final void output(Object object) { + mOutputConsumer.accept(object); + } +} diff --git a/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/actions/TestActionParams.java b/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/actions/TestActionParams.java new file mode 100644 index 000000000..306113b7d --- /dev/null +++ b/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/actions/TestActionParams.java @@ -0,0 +1,24 @@ +package com.flash3388.flashlib.robot.scheduling.actions; + +import com.flash3388.flashlib.robot.scheduling.Scheduler; + +import java.util.function.Consumer; + +public class TestActionParams { + + private final Scheduler mScheduler; + private final Consumer mOutputConsumer; + + public TestActionParams(Scheduler scheduler, Consumer outputConsumer) { + mScheduler = scheduler; + mOutputConsumer = outputConsumer; + } + + public Scheduler getScheduler() { + return mScheduler; + } + + public Consumer getOutputConsumer() { + return mOutputConsumer; + } +} diff --git a/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/actions/TestActions.java b/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/actions/TestActions.java index 1affb603e..78dfaabfa 100644 --- a/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/actions/TestActions.java +++ b/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/actions/TestActions.java @@ -2,14 +2,10 @@ import benchmark.benchmark.util.GlobalRandom; import benchmark.benchmark.util.Range; -import com.flash3388.flashlib.robot.scheduling.Scheduler; -import com.flash3388.flashlib.time.SystemNanoClock; -import com.flash3388.flashlib.time.Time; import java.util.Collection; import java.util.Random; -import java.util.function.BiFunction; -import java.util.function.Consumer; +import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -18,33 +14,31 @@ public class TestActions { public enum ActionType { SMALL(SmallSizeAction::new), MEDIUM(MediumSizeAction::new), - SHORT_SLEEP((scheduler, outputConsumer)-> - new SleepingAction(scheduler, 1L)), - SMALL_SINGLE_SEQ_GROUP((scheduler, outputConsumer)-> - new GenericSequentialActionGroup(ActionType.SMALL, new Range(1, 1), scheduler, outputConsumer)), - SMALL_MULTI_SEQ_GROUP((scheduler, outputConsumer)-> - new GenericSequentialActionGroup(ActionType.SMALL, new Range(2, 3), scheduler, outputConsumer)) + SHORT_SLEEP((params)-> + new SleepingAction(params, 1L)), + SMALL_SINGLE_SEQ_GROUP((params)-> + new GenericSequentialActionGroup(ActionType.SMALL, new Range(1, 1), params)), + SMALL_MULTI_SEQ_GROUP((params)-> + new GenericSequentialActionGroup(ActionType.SMALL, new Range(2, 3), params)) ; - private final BiFunction, Action> mActionGenerator; + private final Function mActionGenerator; - ActionType(BiFunction, Action> actionGenerator) { + ActionType(Function actionGenerator) { mActionGenerator = actionGenerator; } - public Action generate(Scheduler scheduler, Consumer outputConsumer) { - return mActionGenerator.apply(scheduler, outputConsumer); + public Action create(TestActionParams params) { + return mActionGenerator.apply(params); } } - public static class SmallSizeAction extends Action { + public static class SmallSizeAction extends TestAction { - private final Consumer mOutputConsumer; private final Random mRandom; - private SmallSizeAction(Scheduler scheduler, Consumer outputConsumer) { - super(scheduler, Time.INVALID); - mOutputConsumer = outputConsumer; + private SmallSizeAction(TestActionParams params) { + super(params); mRandom = new Random(); } @@ -53,21 +47,19 @@ protected void execute() { byte[] bytes = new byte[1024]; mRandom.nextBytes(bytes); - mOutputConsumer.accept(bytes); + output(bytes); } @Override protected void end() { } } - public static class MediumSizeAction extends Action { + public static class MediumSizeAction extends TestAction { - private final Consumer mOutputConsumer; private final Random mRandom; - private MediumSizeAction(Scheduler scheduler, Consumer outputConsumer) { - super(scheduler, Time.INVALID); - mOutputConsumer = outputConsumer; + private MediumSizeAction(TestActionParams params) { + super(params); mRandom = new Random(); } @@ -78,19 +70,19 @@ protected void execute() { .sorted(Integer::compareTo) .collect(Collectors.toList()); - mOutputConsumer.accept(numbers); + output(numbers); } @Override protected void end() { } } - public static class SleepingAction extends Action { + public static class SleepingAction extends TestAction { private final long mSleepTimeMs; - private SleepingAction(Scheduler scheduler, long sleepTimeMs) { - super(scheduler); + private SleepingAction(TestActionParams params, long sleepTimeMs) { + super(params); mSleepTimeMs = sleepTimeMs; } @@ -98,22 +90,24 @@ private SleepingAction(Scheduler scheduler, long sleepTimeMs) { protected void execute() { try { Thread.sleep(mSleepTimeMs); - } catch (InterruptedException e) { } + } catch (InterruptedException e) { + output(e); + } } @Override protected void end() { } } - public static class GenericSequentialActionGroup extends SequentialActionGroup { + public static class GenericSequentialActionGroup extends TestSequentialActionGroup { private GenericSequentialActionGroup(ActionType containedType, Range amountRange, - Scheduler scheduler, Consumer outputConsumer) { - super(scheduler, new SystemNanoClock()); + TestActionParams params) { + super(params); int actionsCount = GlobalRandom.nextIntInRange(amountRange); IntStream.range(0, actionsCount) - .forEach((i)->add(containedType.generate(scheduler, outputConsumer))); + .forEach((i)->add(containedType.create(params))); } } diff --git a/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/actions/TestSequentialActionGroup.java b/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/actions/TestSequentialActionGroup.java new file mode 100644 index 000000000..e208f590f --- /dev/null +++ b/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/actions/TestSequentialActionGroup.java @@ -0,0 +1,19 @@ +package com.flash3388.flashlib.robot.scheduling.actions; + +import com.flash3388.flashlib.time.SystemNanoClock; + +import java.util.function.Consumer; + +public class TestSequentialActionGroup extends SequentialActionGroup { + + private final Consumer mOutputConsumer; + + public TestSequentialActionGroup(TestActionParams params) { + super(params.getScheduler(), new SystemNanoClock()); + mOutputConsumer = params.getOutputConsumer(); + } + + protected final void output(Object object) { + mOutputConsumer.accept(object); + } +} From eea3476e91105ca29903f28ed5d99d2c1798d638 Mon Sep 17 00:00:00 2001 From: Tom Tzook Date: Sat, 16 Nov 2019 13:01:34 +0200 Subject: [PATCH 05/21] generics and collection improvements: making copies in ctors, and generic wildcard params --- .../robot/scheduling/EmptyScheduler.java | 2 +- .../flashlib/robot/hid/GenericHid.java | 12 ++++++------ .../flashlib/robot/hid/custom/CustomHid.java | 14 ++++++++------ .../flashlib/robot/hid/xbox/XboxController.java | 17 ++++++++--------- .../robot/motion/actions/Move2dAction.java | 4 ++-- .../robot/scheduling/ActionsRepository.java | 2 +- .../flashlib/robot/scheduling/Scheduler.java | 2 +- .../robot/scheduling/SingleThreadScheduler.java | 2 +- .../drive/actions/ArcadeDriveAction.java | 4 ++-- .../drive/actions/HolonomicDriveAction.java | 4 ++-- .../systems/drive/actions/OmniDriveAction.java | 4 ++-- .../systems/drive/actions/TankDriveAction.java | 4 ++-- .../util/logging/jul/JulLoggerBuilder.java | 4 ++-- .../flashlib/vision/ImageDelegator.java | 9 +++++---- .../vision/jpeg/client/MjpegClient.java | 1 + .../vision/processing/VisionPipeline.java | 13 +++++++------ .../vision/processing/analysis/Analysis.java | 2 +- 17 files changed, 52 insertions(+), 48 deletions(-) diff --git a/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/EmptyScheduler.java b/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/EmptyScheduler.java index ce49287a4..ea9c08304 100644 --- a/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/EmptyScheduler.java +++ b/flashlibj/src/jmh/java/com/flash3388/flashlib/robot/scheduling/EmptyScheduler.java @@ -19,7 +19,7 @@ public void stopAllActions() { } @Override - public void stopActionsIf(Predicate removalPredicate) { + public void stopActionsIf(Predicate removalPredicate) { } diff --git a/flashlibj/src/main/java/com/flash3388/flashlib/robot/hid/GenericHid.java b/flashlibj/src/main/java/com/flash3388/flashlib/robot/hid/GenericHid.java index 921bc1df4..33cd40a4b 100644 --- a/flashlibj/src/main/java/com/flash3388/flashlib/robot/hid/GenericHid.java +++ b/flashlibj/src/main/java/com/flash3388/flashlib/robot/hid/GenericHid.java @@ -21,17 +21,17 @@ public class GenericHid implements Hid { public GenericHid(Clock clock, HidInterface hidInterface, int channel, int axisCount, int buttonCount, int povsCount, Time buttonPressTime){ mChannel = channel; - mAxes = IntStream.range(0, axisCount) + mAxes = Collections.unmodifiableList(IntStream.range(0, axisCount) .mapToObj((i) -> new HidAxis(hidInterface, channel, i)) - .collect(Collectors.toList()); + .collect(Collectors.toList())); - mButtons = IntStream.range(0, buttonCount) + mButtons = Collections.unmodifiableList(IntStream.range(0, buttonCount) .mapToObj((i) -> new HidButton(clock, buttonPressTime, hidInterface, channel, i)) - .collect(Collectors.toList()); + .collect(Collectors.toList())); - mPovs = IntStream.range(0, povsCount) + mPovs = Collections.unmodifiableList(IntStream.range(0, povsCount) .mapToObj((i) -> new Pov(hidInterface, channel, i)) - .collect(Collectors.toList()); + .collect(Collectors.toList())); } public GenericHid(int channel, int axisCount, int buttonCount, int povsCount) { diff --git a/flashlibj/src/main/java/com/flash3388/flashlib/robot/hid/custom/CustomHid.java b/flashlibj/src/main/java/com/flash3388/flashlib/robot/hid/custom/CustomHid.java index 35f9e1707..6263132f1 100644 --- a/flashlibj/src/main/java/com/flash3388/flashlib/robot/hid/custom/CustomHid.java +++ b/flashlibj/src/main/java/com/flash3388/flashlib/robot/hid/custom/CustomHid.java @@ -8,6 +8,8 @@ import com.flash3388.flashlib.robot.hid.NoSuchPovException; import com.flash3388.flashlib.robot.hid.Pov; +import java.util.Collections; +import java.util.HashMap; import java.util.Map; public class CustomHid implements Hid { @@ -19,9 +21,9 @@ public class CustomHid implements Hid { public CustomHid(int channel, Map axes, Map buttons, Map povs) { mChannel = channel; - mAxes = axes; - mButtons = buttons; - mPovs = povs; + mAxes = new HashMap<>(axes); + mButtons = new HashMap<>(buttons); + mPovs = new HashMap<>(povs); } @Override @@ -45,7 +47,7 @@ public int getAxisCount() { @Override public Iterable axes() { - return mAxes.values(); + return Collections.unmodifiableCollection(mAxes.values()); } @Override @@ -64,7 +66,7 @@ public int getButtonCount() { @Override public Iterable