From gdub at openjdk.org Tue Mar 7 16:44:14 2023 From: gdub at openjdk.org (Gilles Duboscq) Date: Tue, 7 Mar 2023 16:44:14 GMT Subject: RFR: Allow forcing the use of compiler hints using a system property Message-ID: Using `-Djmh.compilerhints.mode=true` will force the use of compiler hints. `-Djmh.compilerhints.mode=false` will prevent the use of compiler hints. When the system property is not set, the current beahviour based on vm name and version will be used by default. This is especially useful when working with uncommon / rare JVMs or when adding compiler hints support to a new JVM. I considered auto-detecting support for compiler hints but that didn't fit very well in the current code and required much more intrusive changes. ------------- Commit messages: - Allow forcing the use of compiler hints using a system property Changes: https://git.openjdk.org/jmh/pull/96/files Webrev: https://webrevs.openjdk.org/?repo=jmh&pr=96&range=00 Stats: 5 lines in 1 file changed: 5 ins; 0 del; 0 mod Patch: https://git.openjdk.org/jmh/pull/96.diff Fetch: git fetch https://git.openjdk.org/jmh pull/96/head:pull/96 PR: https://git.openjdk.org/jmh/pull/96 From kasperni at gmail.com Tue Mar 14 20:44:41 2023 From: kasperni at gmail.com (Kasper Nielsen) Date: Tue, 14 Mar 2023 20:44:41 +0000 Subject: Measuring class loading time Message-ID: Hi, I'm contemplating converting some class generation functionality to use indy to avoid some startup latency. However, I would really like to get an idea of any time savings first and I'm not completely sure about the best strategy for measuring this. Would measuring Lookup.defineHiddenClass with pre-generated byte arrays be fine? Or is there a significant overhead of setting up a class loader for just a single class compared to using the system class loader to load classes at application startup? An alternative would be to create a class loader and load 100 similar classes but with different names to amortize the cost of setting up a class loader. Also, are there any pitfalls with how this might interact with the VM I should be aware of? I feel like there may be strange interactions that make this difficult to measure in a reliable way. Thanks, Kasper From shade at openjdk.org Thu Mar 23 10:19:13 2023 From: shade at openjdk.org (Aleksey Shipilev) Date: Thu, 23 Mar 2023 10:19:13 GMT Subject: RFR: 7903448: JMH: Override the use of compiler hints using a system property In-Reply-To: References: Message-ID: On Tue, 7 Mar 2023 16:37:01 GMT, Gilles Duboscq wrote: > Using `-Djmh.compilerhints.mode=true` will force the use of compiler hints. `-Djmh.compilerhints.mode=false` will prevent the use of compiler hints. When the system property is not set, the current beahviour based on vm name and version will be used by default. > > This is especially useful when working with uncommon / rare JVMs or when adding compiler hints support to a new JVM. > > I considered auto-detecting support for compiler hints but that didn't fit very well in the current code and required much more intrusive changes. Okay, I understand the use case. But I also think that accepting a boolean as `jmh.compilerhints.mode` is ambiguous, especially if we ask questions about defaults :) It would be cleaner to do it like we do it for Blackholes: public enum CompilerHintsMode { FORCE_ON("Forced on"), FORCE_OFF("Forced off"), AUTO("Automatically selected"), } Then parse that enum off the `jmh.compilerhints.mode`, default to `AUTO`. ------------- PR Review: https://git.openjdk.org/jmh/pull/96#pullrequestreview-1354264175 From gdub at openjdk.org Thu Mar 23 11:25:19 2023 From: gdub at openjdk.org (Gilles Duboscq) Date: Thu, 23 Mar 2023 11:25:19 GMT Subject: RFR: 7903448: JMH: Override the use of compiler hints using a system property In-Reply-To: References: Message-ID: On Tue, 7 Mar 2023 16:37:01 GMT, Gilles Duboscq wrote: > Using `-Djmh.compilerhints.mode=true` will force the use of compiler hints. `-Djmh.compilerhints.mode=false` will prevent the use of compiler hints. When the system property is not set, the current beahviour based on vm name and version will be used by default. > > This is especially useful when working with uncommon / rare JVMs or when adding compiler hints support to a new JVM. > > I considered auto-detecting support for compiler hints but that didn't fit very well in the current code and required much more intrusive changes. Good idea. I'll do ------------- PR Comment: https://git.openjdk.org/jmh/pull/96#issuecomment-1481015893 From shade at openjdk.org Thu Mar 23 12:01:56 2023 From: shade at openjdk.org (Aleksey Shipilev) Date: Thu, 23 Mar 2023 12:01:56 GMT Subject: RFR: 7903448: JMH: Override the use of compiler hints using a system property In-Reply-To: References: Message-ID: On Tue, 7 Mar 2023 16:37:01 GMT, Gilles Duboscq wrote: > Using `-Djmh.compilerhints.mode=true` will force the use of compiler hints. `-Djmh.compilerhints.mode=false` will prevent the use of compiler hints. When the system property is not set, the current beahviour based on vm name and version will be used by default. > > This is especially useful when working with uncommon / rare JVMs or when adding compiler hints support to a new JVM. > > I considered auto-detecting support for compiler hints but that didn't fit very well in the current code and required much more intrusive changes. Also, go to https://github.com/gilles-duboscq/jmh/actions and press a large green button to enable PR testing. ------------- PR Comment: https://git.openjdk.org/jmh/pull/96#issuecomment-1481065749 From gdub at openjdk.org Thu Mar 23 18:45:29 2023 From: gdub at openjdk.org (Gilles Duboscq) Date: Thu, 23 Mar 2023 18:45:29 GMT Subject: RFR: 7903448: JMH: Override the use of compiler hints using a system property [v2] In-Reply-To: References: Message-ID: <6ACmXebPaDuPbhw-0nkSCYlUf1cw0mZRU90J27sDIwo=.bd644660-c5b6-4e44-95a8-240e3a4f1118@github.com> > Using `-Djmh.compilerhints.mode=true` will force the use of compiler hints. `-Djmh.compilerhints.mode=false` will prevent the use of compiler hints. When the system property is not set, the current beahviour based on vm name and version will be used by default. > > This is especially useful when working with uncommon / rare JVMs or when adding compiler hints support to a new JVM. > > I considered auto-detecting support for compiler hints but that didn't fit very well in the current code and required much more intrusive changes. Gilles Duboscq has refreshed the contents of this pull request, and previous commits have been removed. The incremental views will show differences compared to the previous content of the PR. The pull request contains one new commit since the last revision: Allow forcing the use of compiler hints using a system property Using `-Djmh.compilerhints.mode=FORCE_ON` will force the use of compiler hints. `-Djmh.compilerhints.mode=FORCE_OFF` will prevent the use of compiler hints. When the system property is not set, or when it is set to `AUTO`, the current beahviour based on vm name and version will be used. ------------- Changes: - all: https://git.openjdk.org/jmh/pull/96/files - new: https://git.openjdk.org/jmh/pull/96/files/8996a68e..5e550e44 Webrevs: - full: https://webrevs.openjdk.org/?repo=jmh&pr=96&range=01 - incr: https://webrevs.openjdk.org/?repo=jmh&pr=96&range=00-01 Stats: 49 lines in 2 files changed: 39 ins; 0 del; 10 mod Patch: https://git.openjdk.org/jmh/pull/96.diff Fetch: git fetch https://git.openjdk.org/jmh.git pull/96/head:pull/96 PR: https://git.openjdk.org/jmh/pull/96 From gdub at openjdk.org Thu Mar 23 18:45:32 2023 From: gdub at openjdk.org (Gilles Duboscq) Date: Thu, 23 Mar 2023 18:45:32 GMT Subject: RFR: 7903448: JMH: Override the use of compiler hints using a system property In-Reply-To: References: Message-ID: On Tue, 7 Mar 2023 16:37:01 GMT, Gilles Duboscq wrote: > Using `-Djmh.compilerhints.mode=true` will force the use of compiler hints. `-Djmh.compilerhints.mode=false` will prevent the use of compiler hints. When the system property is not set, the current beahviour based on vm name and version will be used by default. > > This is especially useful when working with uncommon / rare JVMs or when adding compiler hints support to a new JVM. > > I considered auto-detecting support for compiler hints but that didn't fit very well in the current code and required much more intrusive changes. I have changed the `jmh.compilerhints.mode` system property to access the 3 suggested values and implemented it following the implementation of the blackhole modes. ------------- PR Comment: https://git.openjdk.org/jmh/pull/96#issuecomment-1481715589 From shade at openjdk.org Fri Mar 24 09:09:02 2023 From: shade at openjdk.org (Aleksey Shipilev) Date: Fri, 24 Mar 2023 09:09:02 GMT Subject: RFR: 7903448: JMH: Override the use of compiler hints using a system property [v2] In-Reply-To: <6ACmXebPaDuPbhw-0nkSCYlUf1cw0mZRU90J27sDIwo=.bd644660-c5b6-4e44-95a8-240e3a4f1118@github.com> References: <6ACmXebPaDuPbhw-0nkSCYlUf1cw0mZRU90J27sDIwo=.bd644660-c5b6-4e44-95a8-240e3a4f1118@github.com> Message-ID: On Thu, 23 Mar 2023 18:45:29 GMT, Gilles Duboscq wrote: >> Using `-Djmh.compilerhints.mode=true` will force the use of compiler hints. `-Djmh.compilerhints.mode=false` will prevent the use of compiler hints. When the system property is not set, the current beahviour based on vm name and version will be used by default. >> >> This is especially useful when working with uncommon / rare JVMs or when adding compiler hints support to a new JVM. >> >> I considered auto-detecting support for compiler hints but that didn't fit very well in the current code and required much more intrusive changes. > > Gilles Duboscq has refreshed the contents of this pull request, and previous commits have been removed. The incremental views will show differences compared to the previous content of the PR. The pull request contains one new commit since the last revision: > > Allow forcing the use of compiler hints using a system property > > Using `-Djmh.compilerhints.mode=FORCE_ON` will force the use of compiler > hints. `-Djmh.compilerhints.mode=FORCE_OFF` will prevent the use of compiler > hints. When the system property is not set, or when it is set to `AUTO`, > the current beahviour based on vm name and version will be used. I have more comments, apologies :) jmh-core/src/main/java/org/openjdk/jmh/runner/CompilerHints.java line 108: > 106: FORCE_ON("Forced on"), > 107: FORCE_OFF("Forced off"), > 108: AUTO("Automatically selected"); I am thinking it would be easier if we separate `AUTO_ON` and `AUTO_OFF`? This would eliminate `compilerHintsEnabled`, because you can just use `compilerHintsSelect` for everything, and treat its `null` is uninitialized. Might want to introduce a few helper methods in this enum, like `isAuto()` and `isEnabled()`. jmh-core/src/main/java/org/openjdk/jmh/runner/CompilerHints.java line 134: > 132: */ > 133: private static boolean compilerHintsEnabled() { > 134: if (compilerHintsEnabled != null) { Where do we set `compilerHintsEnabled`? I think it needs to be set before every `return` from this method. jmh-core/src/main/java/org/openjdk/jmh/runner/CompilerHints.java line 232: > 230: public static void addCompilerHints(List command) { > 231: if (!compilerHintsEnabled()) { > 232: if (compilerHintsSelect() == CompilerHintsSelect.AUTO) { Collapsible `if`-s. I'd say: if (compilerHintsSelect() == CompilerHintsSelect.AUTO_OFF) { ... } jmh-core/src/main/java/org/openjdk/jmh/runner/CompilerHints.java line 235: > 233: System.err.println("WARNING: Not a HotSpot compiler command compatible VM (\"" > 234: + System.getProperty("java.vm.name") + "-" + System.getProperty("java.version") > 235: + "\"), compilerHints are disabled."); While you are at it, please change "compilerHints" -> "compiler hints". jmh-core/src/main/java/org/openjdk/jmh/runner/CompilerHints.java line 437: > 435: public static void printHints(PrintStream out) { > 436: out.print("# Compiler hints: " + (compilerHintsEnabled() ? "enabled" : "disabled") + " (" + compilerHintsSelect().desc() + ")"); > 437: out.println(); Let's print this only if `!compilerHintsSelect().isAuto()`. The normal use case is having compiler hints transparently enabled. This is quite a bit different from Blackhole that does have a normal variance in settings... ------------- Changes requested by shade (Committer). PR Review: https://git.openjdk.org/jmh/pull/96#pullrequestreview-1356241031 PR Review Comment: https://git.openjdk.org/jmh/pull/96#discussion_r1147285403 PR Review Comment: https://git.openjdk.org/jmh/pull/96#discussion_r1147277919 PR Review Comment: https://git.openjdk.org/jmh/pull/96#discussion_r1147281285 PR Review Comment: https://git.openjdk.org/jmh/pull/96#discussion_r1147290287 PR Review Comment: https://git.openjdk.org/jmh/pull/96#discussion_r1147279761 From duke at openjdk.org Fri Mar 24 10:05:06 2023 From: duke at openjdk.org (bbrehm) Date: Fri, 24 Mar 2023 10:05:06 GMT Subject: RFR: Allow setting of opsPerInvocation from setup functions Message-ID: <00k2mIKl2NShhc3UzANy4W5121VTwottPTj69-xuZ0s=.655ebbb2-28e2-4e06-b0f4-a3d086745f49@github.com> In many cases, opsPerInvocation is known at the @Setup function, but cannot be reasonably known at any other point. This example is somewhat lame in that regard; I actually needed that for some not-quite-micro benchmarks (the setup function loads real-ish data from disk, and the opsPerInvocation depends on the data that has been loaded). Since every good example teaches multiple things, I added one that also warns about the branch history table stitching together surprisingly long patterns. The super-duper correct way of doing this example (cf https://discourse.julialang.org/t/psa-microbenchmarks-remember-branch-history/17436) would be to have constant opsPerInvocation and one large array; then a smaller (@Param) array is copied into that multiple times. Thus we could exclude effects of memory hierarchy. That would look quite unnatural and harder to relate to "normal looking" code (and there are no effects of memory anyway, since first, the benchmark is too slow to saturate DRAM bandwidth, and second even the largest set fits into L2). ------------- Commit messages: - add setter function for opsPerInvocation; use it in example - add example, using reflection Changes: https://git.openjdk.org/jmh/pull/97/files Webrev: https://webrevs.openjdk.org/?repo=jmh&pr=97&range=00 Stats: 163 lines in 2 files changed: 162 ins; 0 del; 1 mod Patch: https://git.openjdk.org/jmh/pull/97.diff Fetch: git fetch https://git.openjdk.org/jmh.git pull/97/head:pull/97 PR: https://git.openjdk.org/jmh/pull/97 From shade at openjdk.org Fri Mar 24 10:05:06 2023 From: shade at openjdk.org (Aleksey Shipilev) Date: Fri, 24 Mar 2023 10:05:06 GMT Subject: RFR: Allow setting of opsPerInvocation from setup functions In-Reply-To: <00k2mIKl2NShhc3UzANy4W5121VTwottPTj69-xuZ0s=.655ebbb2-28e2-4e06-b0f4-a3d086745f49@github.com> References: <00k2mIKl2NShhc3UzANy4W5121VTwottPTj69-xuZ0s=.655ebbb2-28e2-4e06-b0f4-a3d086745f49@github.com> Message-ID: On Fri, 17 Mar 2023 12:54:38 GMT, bbrehm wrote: > In many cases, opsPerInvocation is known at the @Setup function, but cannot be reasonably known at any other point. This example is somewhat lame in that regard; I actually needed that for some not-quite-micro benchmarks (the setup function loads real-ish data from disk, and the opsPerInvocation depends on the data that has been loaded). > > Since every good example teaches multiple things, I added one that also warns about the branch history table stitching together surprisingly long patterns. > > The super-duper correct way of doing this example (cf https://discourse.julialang.org/t/psa-microbenchmarks-remember-branch-history/17436) would be to have constant opsPerInvocation and one large array; then a smaller (@Param) array is copied into that multiple times. Thus we could exclude effects of memory hierarchy. That would look quite unnatural and harder to relate to "normal looking" code (and there are no effects of memory anyway, since first, the benchmark is too slow to saturate DRAM bandwidth, and second even the largest set fits into L2). Interesting example! However, the benchmark parameters (like all other params) are supposed to be immutable for the run. It is pure luck that all uses of `opsPerInvocation` happen after `@Setup`, and thus calculations are not subtly broken. This is not actually guaranteed. Trying to reconcile what to do when the benchmark code mutates its own configuration is a much larger task. (Things to think about: Do we allow to set `opsPerInvocation` multiple times during the run? Do we allow doing this in `@Setup(Level.Invocation)`?) The usual answer for things that cannot be captured in declarative form via annotations is going to Java API and doing it in imperative form there. For your example, it would be something like (drafting from memory, might not readily compile): public static void main(String[] args) throws RunnerException { Options parent = new OptionsBuilder() .include(".*" + JMHSample_40_InfraParamNormalization.class.getSimpleName() + ".*") .addProfiler(LinuxPerfNormProfiler.class) .build(); for (int size : new int[] { 100, 1000, 5000, 10000, 100000 }) { Options opts = new OptionsBuilder() .parent(parent) .param("size", String.valueOf(size)) .operationsPerInvocation(size) .build(); new Runner(opt).run(); } } ------------- PR Comment: https://git.openjdk.org/jmh/pull/97#issuecomment-1480941620 From duke at openjdk.org Fri Mar 24 16:57:33 2023 From: duke at openjdk.org (bbrehm) Date: Fri, 24 Mar 2023 16:57:33 GMT Subject: RFR: Allow setting of opsPerInvocation from setup functions In-Reply-To: References: <00k2mIKl2NShhc3UzANy4W5121VTwottPTj69-xuZ0s=.655ebbb2-28e2-4e06-b0f4-a3d086745f49@github.com> Message-ID: <_CyNzQtNiLV1ubNvudHyo-oUDpv0-cb80H13GAkxm1A=.53e24730-3bfe-4486-b3ca-535c46ad51f3@github.com> On Thu, 23 Mar 2023 10:27:03 GMT, Aleksey Shipilev wrote: >Interesting example! Thanks! I think the example is fun, the issue is pervasive in micro-benchmarking, and "branch history table stitching" (making up a word here) is not a very well-known effect. So I think some form of this example would be worthwhile to add, even without dynamic opsPerInvocation. I could change the example to work with static opsPerInvocation, following the variant in https://discourse.julialang.org/t/psa-microbenchmarks-remember-branch-history/17436 This has the advantage of obviously excluding memory as the source of the effect (no one can claim that this is due to the working set still being in L1 from the last benchmark iteration), and the disadvantage of being less relatable: Iterating over a length 100k array that has 100 copies of the same random length 1000 pattern looks unnatural, and furthermore obscures the effect that this is a genuine benchmarking artifact -- the CPU cheats because the branch history table remembers previous iterations from the hidden jmh-generated benchmarking loop. >Things to think about: Do we allow to set opsPerInvocation multiple times during the run? Do we allow doing this in @Setup(Level.Invocation)? True enough. We'd need to document the specifics of the implementation (which is: You can overwrite opsPerInvocation as often as you want, but only the last write counts). That issue alone could make this PR non-workable as stable public API :( > The usual answer for things that cannot be captured in declarative form via annotations is going to Java API ... I'd consider doing that instead if there was a sensible API to individually configure benchmarks and combine them into a single `Runner` for output formatting. Alas, almost all relevant functions in `Runner` are `private` instead of `protected`. Nevertheless, I think figuring out or documenting a low-effort way of proper rescaling / dynamic opsPerInvocation would be worthwhile. Maybe the rescaling operation happening in the generated functions like `public BenchmarkTaskResult Foo_Throughput(InfraControl control, ThreadParams threadParams) throws Throwable` could get a hook? How would e.g. _you_ use jmh to benchmark a piece of complex code, where performance is meaningful only relative to a corpus of test-data (> 100 mb), like e.g. parse a stream of webserver logs? Obviously the test-data cannot be known at compile time, and obviously some kind of normalization is necessary, otherwise the time will only reflect the size of the corpus (and it's up to the user to select a corpus that matches the intended deployment, and to experiment to decide between cycles-per-byte, messages-per-second or whatever metric turns out to be most meaningful). Using reflection to modify opsPerInvocation is good enough for my needs at the moment, now that I figured out how to do that. But I'd feel very dirty recommending that to other people. ------------- PR Comment: https://git.openjdk.org/jmh/pull/97#issuecomment-1483118104 From duke at openjdk.org Sun Mar 26 08:43:46 2023 From: duke at openjdk.org (Andrei Rybak) Date: Sun, 26 Mar 2023 08:43:46 GMT Subject: RFR: Optional refactoring Message-ID: This is a follow-up to the email https://mail.openjdk.org/pipermail/jmh-dev/2023-January/003562.html `java.util.Optional` isn't `Serializeable`. Because of that `org.openjdk.jmh.runner.options.TestOptions` fails with `java.io.NotSerializableException: java.util.Optional`, when `org.openjdk.jmh.util.Optional` is completely replaced with `java.util.Optional`. See [test results on branch `java-util-optional`](https://github.com/rybak/jmh/actions/runs/4326921418), ([one commit](https://github.com/rybak/jmh/commit/25b9cb382be7285a51446976247d036ac855fc91) on top of initial state of this PR). I didn't look further into possibility of removing `Optional`s as fields of class `CommandLineOptions`. I think that the refactoring up until the drop-in replacement to `java.util.Optional` might still be worth it, at least from the point of making it more approachable for people who are familiar with `java.util.Optional`. So here are these changes for your consideration. Details are in the commit messages. ------------- Commit messages: - Optional: rename hasValue() to isPresent() - Optional: rename eitherOf() to ofNullable() - Optional: rename none() to empty() - OptionsBuilder: refactor usage of Optional#orAnother() - Runner: replace orAnother() with orElseGet() - OptionsBuilder: extract method getOrOther - OptionsBuilder: don't pass empty Optional to orAnother() Changes: https://git.openjdk.org/jmh/pull/98/files Webrev: https://webrevs.openjdk.org/?repo=jmh&pr=98&range=00 Stats: 323 lines in 12 files changed: 9 ins; 114 del; 200 mod Patch: https://git.openjdk.org/jmh/pull/98.diff Fetch: git fetch https://git.openjdk.org/jmh.git pull/98/head:pull/98 PR: https://git.openjdk.org/jmh/pull/98 From shade at openjdk.org Mon Mar 27 10:26:00 2023 From: shade at openjdk.org (Aleksey Shipilev) Date: Mon, 27 Mar 2023 10:26:00 GMT Subject: RFR: Optional refactoring In-Reply-To: References: Message-ID: On Sun, 26 Mar 2023 08:38:53 GMT, Andrei Rybak wrote: > This is a follow-up to the email https://mail.openjdk.org/pipermail/jmh-dev/2023-January/003562.html > > `java.util.Optional` isn't `Serializeable`. Because of that `org.openjdk.jmh.runner.options.TestOptions` fails with `java.io.NotSerializableException: java.util.Optional`, when `org.openjdk.jmh.util.Optional` is completely replaced with `java.util.Optional`. See [test results on branch `java-util-optional`](https://github.com/rybak/jmh/actions/runs/4326921418), ([one commit](https://github.com/rybak/jmh/commit/25b9cb382be7285a51446976247d036ac855fc91) on top of initial state of this PR). > > I didn't look further into possibility of removing `Optional`s as fields of class `CommandLineOptions`. I think that the refactoring up until the drop-in replacement to `java.util.Optional` might still be worth it, at least from the point of making it more approachable for people who are familiar with `java.util.Optional`. So here are these changes for your consideration. Details are in the commit messages. I believe `Options` and the relevant classes being `Serializable` is the reminiscent of the JMH a decade ago, when the full options carrier was passed via the binary link to forked VM. Today, `BinaryLinkClient` and `BinaryLinkServer` are passing the separate `*Params` objects. So, technically, we can avoid the issue with `j.l.Optional` being non-`Serializable` by dropping the test. But, this highlights another issue: changing to `j.l.Optional` changes the public interface `Options`. This is the API-breaking change, AFAICS. The technical benefit of changing to `j.l.Optional` should outweigh the hassle of dealing with this breakage. Is there a benefit, apart from what you already identified ("People might be more familiar with `j.l.Optional`")? ------------- PR Comment: https://git.openjdk.org/jmh/pull/98#issuecomment-1484891835 From duke at openjdk.org Mon Mar 27 11:31:59 2023 From: duke at openjdk.org (Andrei Rybak) Date: Mon, 27 Mar 2023 11:31:59 GMT Subject: RFR: Optional refactoring In-Reply-To: References: Message-ID: <-AaMeQzRkLfdiTMiVS8SiBJ-9dPEz3Gz18zjsuJfzZ4=.a3fc092f-a596-4160-9803-c52eb9c5b571@github.com> On Mon, 27 Mar 2023 10:23:33 GMT, Aleksey Shipilev wrote: > But, this highlights another issue: changing to `j.l.Optional` changes the public interface `Options`. This is the API-breaking change, AFAICS. I hadn't considered that, my bad. > Is there a benefit, apart from what you already identified ("People might be more familiar with `j.l.Optional`")? No, I don't know of other benefits. ------------- PR Comment: https://git.openjdk.org/jmh/pull/98#issuecomment-1484978165 From shade at openjdk.org Tue Mar 28 12:20:07 2023 From: shade at openjdk.org (Aleksey Shipilev) Date: Tue, 28 Mar 2023 12:20:07 GMT Subject: RFR: Optional refactoring In-Reply-To: References: Message-ID: On Sun, 26 Mar 2023 08:38:53 GMT, Andrei Rybak wrote: > This is a follow-up to the email https://mail.openjdk.org/pipermail/jmh-dev/2023-January/003562.html > > `java.util.Optional` isn't `Serializeable`. Because of that `org.openjdk.jmh.runner.options.TestOptions` fails with `java.io.NotSerializableException: java.util.Optional`, when `org.openjdk.jmh.util.Optional` is completely replaced with `java.util.Optional`. See [test results on branch `java-util-optional`](https://github.com/rybak/jmh/actions/runs/4326921418), ([one commit](https://github.com/rybak/jmh/commit/25b9cb382be7285a51446976247d036ac855fc91) on top of initial state of this PR). > > I didn't look further into possibility of removing `Optional`s as fields of class `CommandLineOptions`. I think that the refactoring up until the drop-in replacement to `java.util.Optional` might still be worth it, at least from the point of making it more approachable for people who are familiar with `java.util.Optional`. So here are these changes for your consideration. Details are in the commit messages. All right, then this would not work, unfortunately. Close this PR if you agree. We can always reopen it, if needed later. ------------- PR Comment: https://git.openjdk.org/jmh/pull/98#issuecomment-1486775921 From duke at openjdk.org Tue Mar 28 12:54:58 2023 From: duke at openjdk.org (Andrei Rybak) Date: Tue, 28 Mar 2023 12:54:58 GMT Subject: RFR: Optional refactoring [v2] In-Reply-To: References: Message-ID: > This is a follow-up to the email https://mail.openjdk.org/pipermail/jmh-dev/2023-January/003562.html > > `java.util.Optional` isn't `Serializeable`. Because of that `org.openjdk.jmh.runner.options.TestOptions` fails with `java.io.NotSerializableException: java.util.Optional`, when `org.openjdk.jmh.util.Optional` is completely replaced with `java.util.Optional`. See [test results on branch `java-util-optional`](https://github.com/rybak/jmh/actions/runs/4326921418), ([one commit](https://github.com/rybak/jmh/commit/25b9cb382be7285a51446976247d036ac855fc91) on top of initial state of this PR). > > I didn't look further into possibility of removing `Optional`s as fields of class `CommandLineOptions`. I think that the refactoring up until the drop-in replacement to `java.util.Optional` might still be worth it, at least from the point of making it more approachable for people who are familiar with `java.util.Optional`. So here are these changes for your consideration. Details are in the commit messages. Andrei Rybak has refreshed the contents of this pull request, and previous commits have been removed. The incremental views will show differences compared to the previous content of the PR. The pull request contains two new commits since the last revision: - Runner: replace orAnother() with orElseGet() Refactor usage of method org.openjdk.jmh.util.Optional#orAnother in class Runner using new method orElseGet() with lazy `Supplier`s as per comment added in commit db1bc365 (7902576: Lazy query for current JVM args in Runner, 2020-01-20). Clean up imports, while we're here. - OptionsBuilder: don't pass empty Optional to orAnother() Passing an empty Optional to method orAnother() of class org.openjdk.jmh.util.Optional is a no-op. Stop doing it in getters getJvmArgs(), getJvmArgsAppend(), and getJvmArgsPrepend() of class OptionsBuilder. ------------- Changes: - all: https://git.openjdk.org/jmh/pull/98/files - new: https://git.openjdk.org/jmh/pull/98/files/2d8146a5..1e847757 Webrevs: - full: https://webrevs.openjdk.org/?repo=jmh&pr=98&range=01 - incr: https://webrevs.openjdk.org/?repo=jmh&pr=98&range=00-01 Stats: 315 lines in 12 files changed: 114 ins; 8 del; 193 mod Patch: https://git.openjdk.org/jmh/pull/98.diff Fetch: git fetch https://git.openjdk.org/jmh.git pull/98/head:pull/98 PR: https://git.openjdk.org/jmh/pull/98 From duke at openjdk.org Tue Mar 28 12:55:00 2023 From: duke at openjdk.org (Andrei Rybak) Date: Tue, 28 Mar 2023 12:55:00 GMT Subject: RFR: Optional refactoring In-Reply-To: References: Message-ID: <2UvMSRa9873L9X_gmIsGlDPt485IOJtrHkCJIgE-Ikc=.dab8da0d-f9eb-4a55-beb6-4744bc1b7254@github.com> On Sun, 26 Mar 2023 08:38:53 GMT, Andrei Rybak wrote: > This is a follow-up to the email https://mail.openjdk.org/pipermail/jmh-dev/2023-January/003562.html > > `java.util.Optional` isn't `Serializeable`. Because of that `org.openjdk.jmh.runner.options.TestOptions` fails with `java.io.NotSerializableException: java.util.Optional`, when `org.openjdk.jmh.util.Optional` is completely replaced with `java.util.Optional`. See [test results on branch `java-util-optional`](https://github.com/rybak/jmh/actions/runs/4326921418), ([one commit](https://github.com/rybak/jmh/commit/25b9cb382be7285a51446976247d036ac855fc91) on top of initial state of this PR). > > I didn't look further into possibility of removing `Optional`s as fields of class `CommandLineOptions`. I think that the refactoring up until the drop-in replacement to `java.util.Optional` might still be worth it, at least from the point of making it more approachable for people who are familiar with `java.util.Optional`. So here are these changes for your consideration. Details are in the commit messages. I force pushed to drop the commits that are directly related to the replacement with `j.l.Optional`, leaving just two minor cleanups around the usage of `org.openjdk.jmh.util.Optional`. Range-diff: $ git range-diff 2d8146a...1e84775 1: da03a011 = 1: a7762e07 OptionsBuilder: don't pass empty Optional to orAnother() 2: 06a697d9 < -: -------- OptionsBuilder: extract method getOrOther 3: e7505b37 ! 2: 1e847757 Runner: replace orAnother() with orElseGet() @@ Commit message Runner: replace orAnother() with orElseGet() Refactor usage of method org.openjdk.jmh.util.Optional#orAnother in - class Runner using new method orElseGet(). This is part of preparation - for a possible future drop-in replacement of usages of class - org.openjdk.jmh.util.Optional with class java.util.Optional. - - In Java 8, the minimal version that JMH supports at the moment, class - java.util.Optional doesn't have an analogue to JMH's method orAnother(). - A similar method (taking a Supplier of Optional as a parameter), which - could be used instead was added to java.util.Optional in Java 9, see - https://bugs.openjdk.org/browse/JDK-8080418. + class Runner using new method orElseGet() with lazy `Supplier`s as per + comment added in commit db1bc365 (7902576: Lazy query for current JVM + args in Runner, 2020-01-20). Clean up imports, while we're here. ## jmh-core/src/main/java/org/openjdk/jmh/runner/Runner.java ## @@ jmh-core/src/main/java/org/openjdk/jmh/runner/Runner.java: import org.openjdk.jmh.util.Optional; 4: 8e2f4814 < -: -------- OptionsBuilder: refactor usage of Optional#orAnother() 5: b12d5612 < -: -------- Optional: rename none() to empty() 6: 39b5f628 < -: -------- Optional: rename eitherOf() to ofNullable() 7: 2d8146a5 < -: -------- Optional: rename hasValue() to isPresent() ------------- PR Comment: https://git.openjdk.org/jmh/pull/98#issuecomment-1486830490 From shade at openjdk.org Wed Mar 29 11:24:15 2023 From: shade at openjdk.org (Aleksey Shipilev) Date: Wed, 29 Mar 2023 11:24:15 GMT Subject: RFR: 7903451: JMH: Refactor internal Optional usages [v2] In-Reply-To: References: Message-ID: On Tue, 28 Mar 2023 12:54:58 GMT, Andrei Rybak wrote: >> This is a follow-up to the email https://mail.openjdk.org/pipermail/jmh-dev/2023-January/003562.html >> >> `java.util.Optional` isn't `Serializeable`. Because of that `org.openjdk.jmh.runner.options.TestOptions` fails with `java.io.NotSerializableException: java.util.Optional`, when `org.openjdk.jmh.util.Optional` is completely replaced with `java.util.Optional`. See [test results on branch `java-util-optional`](https://github.com/rybak/jmh/actions/runs/4326921418), ([one commit](https://github.com/rybak/jmh/commit/25b9cb382be7285a51446976247d036ac855fc91) on top of initial state of this PR). >> >> I didn't look further into possibility of removing `Optional`s as fields of class `CommandLineOptions`. I think that the refactoring up until the drop-in replacement to `java.util.Optional` might still be worth it, at least from the point of making it more approachable for people who are familiar with `java.util.Optional`. So here are these changes for your consideration. Details are in the commit messages. > > Andrei Rybak has refreshed the contents of this pull request, and previous commits have been removed. The incremental views will show differences compared to the previous content of the PR. The pull request contains two new commits since the last revision: > > - Runner: replace orAnother() with orElseGet() > > Refactor usage of method org.openjdk.jmh.util.Optional#orAnother in > class Runner using new method orElseGet() with lazy `Supplier`s as per > comment added in commit db1bc365 (7902576: Lazy query for current JVM > args in Runner, 2020-01-20). Clean up imports, while we're here. > - OptionsBuilder: don't pass empty Optional to orAnother() > > Passing an empty Optional to method orAnother() of class > org.openjdk.jmh.util.Optional is a no-op. Stop doing it in getters > getJvmArgs(), getJvmArgsAppend(), and getJvmArgsPrepend() of class > OptionsBuilder. jmh-core/src/main/java/org/openjdk/jmh/runner/Runner.java line 481: > 479: () -> benchmark.getJvmArgs().orElseGet( > 480: () -> ManagementFactory.getRuntimeMXBean().getInputArguments()))); > 481: Indentation looks a bit odd to me... Suggestion: jvmArgs.addAll(options.getJvmArgs() .orElseGet(() -> benchmark.getJvmArgs() .orElseGet(() -> ManagementFactory.getRuntimeMXBean().getInputArguments()) )); jmh-core/src/main/java/org/openjdk/jmh/util/Optional.java line 55: > 53: } > 54: > 55: public T orElseGet(Supplier alternativeSupplier) { `orElseFrom`? jmh-core/src/main/java/org/openjdk/jmh/util/Optional.java line 56: > 54: > 55: public T orElseGet(Supplier alternativeSupplier) { > 56: return val != null ? val : alternativeSupplier.get(); Matching style for surrounding code: Suggestion: return (val == null) ? alternativeSupplier.get() : val; ------------- PR Review Comment: https://git.openjdk.org/jmh/pull/98#discussion_r1151780674 PR Review Comment: https://git.openjdk.org/jmh/pull/98#discussion_r1150690264 PR Review Comment: https://git.openjdk.org/jmh/pull/98#discussion_r1150689052