From davidmichaelkarr at gmail.com Mon Oct 1 01:44:51 2018 From: davidmichaelkarr at gmail.com (David Karr) Date: Sun, 30 Sep 2018 18:44:51 -0700 Subject: Average time computation just prints out "10??" In-Reply-To: <8519bb49-4ea6-5a5e-ca75-eadf52db2949@redhat.com> References: <5bafe795.1c69fb81.376c4.f343@mx.google.com> <8519bb49-4ea6-5a5e-ca75-eadf52db2949@redhat.com> Message-ID: On Sun, Sep 30, 2018 at 4:34 AM Aleksey Shipilev wrote: > On 09/30/2018 03:02 AM, David Karr wrote: > > On Sat, Sep 29, 2018 at 4:57 PM Bernd Eckenfels > > wrote: > > I guess that's an improvement. I still can't read it in my text editor, > but > > I can paste it into my browser and see what it was supposed to be > > printing. This produces a text line like this: > > ----------------- > > # Warmup Iteration 1: ? 10?? s/op > > ----------------- > > > > Why did the JMH implementors decide to introduce the complexity of > unicode > > into this? This should be simple textual information. I shouldn't have > to > > work this hard to get this. > > Maintainer's perspective: in the year 2018, JMH or any other power user > tool should be not be held > hostage by environments that do not properly support Unicode. Notice, for > example, how browsers and > mail clients show this correctly. > > Anyway, "? 10?? s/op" is the sign that the units selected are very far off > default precision. The > order of magnitude gives you the hint by how much, without letting you use > the low-precision data. > Or, as in this case, raise the question what is printed exactly -- think > about this as a glorified > Not-A-Number value. In this example, time units should be microseconds, > not seconds. > Ok, so HOW do I set the time units to microseconds? I tried adding the following as a class annotation: @Measurement(timeUnit = TimeUnit.MICROSECONDS) This didn't seem to make much difference. I still see the encoded characters in all the results, and when I view it in the browser, it shows numbers like 10**-5, and it still shows "s/op", as if the time units are still seconds. > -Aleksey > > From shade at redhat.com Mon Oct 1 07:50:30 2018 From: shade at redhat.com (Aleksey Shipilev) Date: Mon, 1 Oct 2018 09:50:30 +0200 Subject: Average time computation just prints out "10??" In-Reply-To: References: <5bafe795.1c69fb81.376c4.f343@mx.google.com> <8519bb49-4ea6-5a5e-ca75-eadf52db2949@redhat.com> Message-ID: On 10/01/2018 03:44 AM, David Karr wrote: > On Sun, Sep 30, 2018 at 4:34 AM Aleksey Shipilev > wrote: > On 09/30/2018 03:02 AM, David Karr wrote: > > On Sat, Sep 29, 2018 at 4:57 PM Bernd Eckenfels > printing.? This produces a text line like this: > > ----------------- > > # Warmup Iteration? ?1: ? 10?? s/op > > ----------------- This mentions "warmup" iteration. > Ok, so HOW do I set the time units to microseconds?? I tried adding the following as a class annotation: > > ??? @Measurement(timeUnit = TimeUnit.MICROSECONDS) This sets up "measurement" iteration. Putting the parameters to @Warmup should be enough. -Aleksey From davidmichaelkarr at gmail.com Mon Oct 1 15:27:07 2018 From: davidmichaelkarr at gmail.com (David Karr) Date: Mon, 1 Oct 2018 08:27:07 -0700 Subject: Average time computation just prints out "10??" In-Reply-To: References: <5bafe795.1c69fb81.376c4.f343@mx.google.com> <8519bb49-4ea6-5a5e-ca75-eadf52db2949@redhat.com> Message-ID: On Mon, Oct 1, 2018 at 12:50 AM Aleksey Shipilev wrote: > On 10/01/2018 03:44 AM, David Karr wrote: > > On Sun, Sep 30, 2018 at 4:34 AM Aleksey Shipilev > wrote: > > On 09/30/2018 03:02 AM, David Karr wrote: > > > On Sat, Sep 29, 2018 at 4:57 PM Bernd Eckenfels < > ecki at zusammenkunft.net > > > printing. This produces a text line like this: > > > ----------------- > > > # Warmup Iteration 1: ? 10?? s/op > > > ----------------- > > This mentions "warmup" iteration. > > > Ok, so HOW do I set the time units to microseconds? I tried adding the > following as a class annotation: > > > > @Measurement(timeUnit = TimeUnit.MICROSECONDS) > > This sets up "measurement" iteration. Putting the parameters to @Warmup > should be enough. > That doesn't really seem like a clear answer, but in any case, I changed the class annotation, adding a @Warmup annotation. I let the run finish completely. Every statistic was "s/op", and had the encoded characters. If it matters, here's the entire skeleton of the class: @Measurement(timeUnit = TimeUnit.MICROSECONDS) @Warmup(timeUnit = TimeUnit.MICROSECONDS) public class MyBenchmark { @Benchmark @BenchmarkMode(value = { Mode.AverageTime}) public void createBigDecimalFromFormattedDouble() { ... } @Benchmark @BenchmarkMode(value = { Mode.AverageTime}) public void createBigDecimalFromDoubleWithScale() { ... } } > -Aleksey > > From shade at redhat.com Mon Oct 1 15:32:21 2018 From: shade at redhat.com (Aleksey Shipilev) Date: Mon, 1 Oct 2018 17:32:21 +0200 Subject: Average time computation just prints out "10??" In-Reply-To: References: <5bafe795.1c69fb81.376c4.f343@mx.google.com> <8519bb49-4ea6-5a5e-ca75-eadf52db2949@redhat.com> Message-ID: On 10/01/2018 05:27 PM, David Karr wrote: > That doesn't really seem like a clear answer, but in any case, I changed the class annotation, > adding a?@Warmup annotation.? I let the run finish completely.? Every statistic was "s/op", and had > the encoded characters. > > If it matters, here's the entire skeleton of the class: > > ??? @Measurement(timeUnit = TimeUnit.MICROSECONDS) > ??? @Warmup(timeUnit = TimeUnit.MICROSECONDS) > ??? public class MyBenchmark { > ??????? @Benchmark > ??????? @BenchmarkMode(value = { Mode.AverageTime}) > ??????? public void createBigDecimalFromFormattedDouble() { > ??????????? ... > ??????? } > ??? > ??????? @Benchmark > ??????? @BenchmarkMode(value = { Mode.AverageTime}) > ??????? public void createBigDecimalFromDoubleWithScale() { > ??????????? ... > ??????? } > ??? } Time units can also be overridden by command line option and/or Java API runner. Please show the complete example, together with the code that runs it? -Aleksey From davidmichaelkarr at gmail.com Mon Oct 1 16:27:25 2018 From: davidmichaelkarr at gmail.com (David Karr) Date: Mon, 1 Oct 2018 09:27:25 -0700 Subject: Average time computation just prints out "10??" In-Reply-To: References: <5bafe795.1c69fb81.376c4.f343@mx.google.com> <8519bb49-4ea6-5a5e-ca75-eadf52db2949@redhat.com> Message-ID: On Mon, Oct 1, 2018 at 8:32 AM Aleksey Shipilev wrote: > On 10/01/2018 05:27 PM, David Karr wrote: > > That doesn't really seem like a clear answer, but in any case, I changed > the class annotation, > > adding a @Warmup annotation. I let the run finish completely. Every > statistic was "s/op", and had > > the encoded characters. > > > > If it matters, here's the entire skeleton of the class: > > > > @Measurement(timeUnit = TimeUnit.MICROSECONDS) > > @Warmup(timeUnit = TimeUnit.MICROSECONDS) > > public class MyBenchmark { > > @Benchmark > > @BenchmarkMode(value = { Mode.AverageTime}) > > public void createBigDecimalFromFormattedDouble() { > > ... > > } > > > > @Benchmark > > @BenchmarkMode(value = { Mode.AverageTime}) > > public void createBigDecimalFromDoubleWithScale() { > > ... > > } > > } > > Time units can also be overridden by command line option and/or Java API > runner. > > Please show the complete example, together with the code that runs it? > There's hardly anything else here of note. On the command line, I run "mvn clean install" and then "java -jar target/benchmarks.jar". I'm certain it doesn't matter, but here are the two method bodies: public void createBigDecimalFromFormattedDouble() { DecimalFormat df = new DecimalFormat("##0.00"); new BigDecimal(df.format(47.0)); new BigDecimal(df.format(324.6)); new BigDecimal(df.format(4.3)); new BigDecimal(df.format(123.93)); new BigDecimal(df.format(997.01)); } public void createBigDecimalFromDoubleWithScale() { DecimalFormat df = new DecimalFormat("##0.00"); new BigDecimal(47.0).setScale(2, BigDecimal.ROUND_HALF_UP); new BigDecimal(324.6).setScale(2, BigDecimal.ROUND_HALF_UP); new BigDecimal(4.3).setScale(2, BigDecimal.ROUND_HALF_UP); new BigDecimal(123.93).setScale(2, BigDecimal.ROUND_HALF_UP); new BigDecimal(997.01).setScale(2, BigDecimal.ROUND_HALF_UP); } > -Aleksey > > > > From shade at redhat.com Mon Oct 1 16:29:50 2018 From: shade at redhat.com (Aleksey Shipilev) Date: Mon, 1 Oct 2018 18:29:50 +0200 Subject: Average time computation just prints out "10??" In-Reply-To: References: <5bafe795.1c69fb81.376c4.f343@mx.google.com> <8519bb49-4ea6-5a5e-ca75-eadf52db2949@redhat.com> Message-ID: <5b243ea4-6b46-d45e-900d-d8e6f5d4df58@redhat.com> On 10/01/2018 06:27 PM, David Karr wrote: > On Mon, Oct 1, 2018 at 8:32 AM Aleksey Shipilev > wrote: > Time units can also be overridden by command line option and/or Java API runner. > > Please show the complete example, together with the code that runs it? > > There's hardly anything else here of note.? On the command line, I run "mvn clean install" and then > "java -jar target/benchmarks.jar". That is really weird. Can you put the project somewhere I can reproduce? -Aleksey From davidmichaelkarr at gmail.com Mon Oct 1 16:39:40 2018 From: davidmichaelkarr at gmail.com (David Karr) Date: Mon, 1 Oct 2018 09:39:40 -0700 Subject: Average time computation just prints out "10??" In-Reply-To: <5b243ea4-6b46-d45e-900d-d8e6f5d4df58@redhat.com> References: <5bafe795.1c69fb81.376c4.f343@mx.google.com> <8519bb49-4ea6-5a5e-ca75-eadf52db2949@redhat.com> <5b243ea4-6b46-d45e-900d-d8e6f5d4df58@redhat.com> Message-ID: I created the following: https://github.com/davidmichaelkarr/jmhUnitsIssues . It's not repeatable in place. I didn't see any way to create the package tree, as opposed to just uploading the two source files. The readme describes where the source file needs to reside in the tree. On Mon, Oct 1, 2018 at 9:29 AM Aleksey Shipilev wrote: > On 10/01/2018 06:27 PM, David Karr wrote: > > On Mon, Oct 1, 2018 at 8:32 AM Aleksey Shipilev > wrote: > > Time units can also be overridden by command line option and/or Java > API runner. > > > > Please show the complete example, together with the code that runs > it? > > > > There's hardly anything else here of note. On the command line, I run > "mvn clean install" and then > > "java -jar target/benchmarks.jar". > > That is really weird. Can you put the project somewhere I can reproduce? > > -Aleksey > > > From shade at redhat.com Mon Oct 1 17:04:23 2018 From: shade at redhat.com (Aleksey Shipilev) Date: Mon, 1 Oct 2018 19:04:23 +0200 Subject: Average time computation just prints out "10??" In-Reply-To: References: <5bafe795.1c69fb81.376c4.f343@mx.google.com> <8519bb49-4ea6-5a5e-ca75-eadf52db2949@redhat.com> <5b243ea4-6b46-d45e-900d-d8e6f5d4df58@redhat.com> Message-ID: On 10/01/2018 06:39 PM, David Karr wrote: > I created the following: https://github.com/davidmichaelkarr/jmhUnitsIssues .? It's not repeatable > in place.? I didn't see any way to create the package tree, as opposed to just uploading the two > source files.? The readme describes where the source file needs to reside in the tree. Oh wait, my bad! You need: @OutputTimeUnit(TimeUnit.MICROSECONDS) The timeunits in @Warmup/@Measurement relate to the durations of the iterations themselves. Or, you can use "-tu us" from command line. -Aleksey From davidmichaelkarr at gmail.com Mon Oct 1 18:42:49 2018 From: davidmichaelkarr at gmail.com (David Karr) Date: Mon, 1 Oct 2018 11:42:49 -0700 Subject: Explain why my two benchmarks are performing differently than I expect? Message-ID: I recently noticed some code in the codebase I work that looks like this (not with a hardcoded value): DecimalFormat df = new DecimalFormat("##0.00"); new BigDecimal(df.format(47.0)); I was pretty sure that was an inefficient way to do this, which I thought should be more like: new BigDecimal(47.0).setScale(2, BigDecimal.ROUND_HALF_UP); So, I built a JMH benchmark that compared these two, and I did see that the throughput numbers for the latter were quite a bit higher than the former (18x). I then went on to try to see what the average times were, and I got stuck for a while trying to figure out the correct annotations to use (and I got answers for that on this list). At the same time, I also expanded each of the two benchmark methods to make more than one call to the BigDecimal constructor, with a few different values. When I finally got my average time values, I was a little confused because the results were showing that the benchmark using DecimalFormat had a lower average time than the one using "setScale". I then changed the benchmark back to show throughput numbers (I've since realized that I can change this on the command line instead of changing the annotations and rebuilding) and that showed that the benchmark using DecimalFormat was getting a higher throughput. This is the results table that I see: Benchmark Mode Cnt Score Error Units MyBenchmark.createBigDecimalFromDoubleWithScale thrpt 25 341705.442 1486.779 ops/s MyBenchmark.createBigDecimalFromFormattedDouble thrpt 25 490130.005 3239.817 ops/s The benchmark code and pom file is at https://github.com/davidmichaelkarr/jmhUnitsIssues . It's not directly compileable in that state, as the source file is in the root of the repo (i'm having some connectivity issues right now, so fixing that is awkward). If you clone it, just move the source file to the package directory, as specified in the readme. I'd appreciate any help understanding why this is behaving oppositely of what I would expect. From shade at redhat.com Mon Oct 1 20:11:27 2018 From: shade at redhat.com (Aleksey Shipilev) Date: Mon, 1 Oct 2018 22:11:27 +0200 Subject: Explain why my two benchmarks are performing differently than I expect? In-Reply-To: References: Message-ID: <3d93a965-adef-f1a5-6760-6cc532f9159e@redhat.com> On 10/01/2018 08:42 PM, David Karr wrote: > I recently noticed some code in the codebase I work that looks like this > (not with a hardcoded value): > > DecimalFormat df = new DecimalFormat("##0.00"); > new BigDecimal(df.format(47.0)); > > I was pretty sure that was an inefficient way to do this, which I thought > should be more like: > > new BigDecimal(47.0).setScale(2, BigDecimal.ROUND_HALF_UP); ... > I'd appreciate any help understanding why this is behaving oppositely of > what I would expect. I think you need to start from JMH Samples: http://hg.openjdk.java.net/code-tools/jmh/file/tip/jmh-samples/src/main/java/org/openjdk/jmh/samples/ Notably JMHSample_08_DeadCode and JMHSample_35_Profilers. -Aleksey From davidmichaelkarr at gmail.com Tue Oct 2 05:25:20 2018 From: davidmichaelkarr at gmail.com (David Karr) Date: Mon, 1 Oct 2018 22:25:20 -0700 Subject: Explain why my two benchmarks are performing differently than I expect? In-Reply-To: <3d93a965-adef-f1a5-6760-6cc532f9159e@redhat.com> References: <3d93a965-adef-f1a5-6760-6cc532f9159e@redhat.com> Message-ID: On Mon, Oct 1, 2018 at 1:11 PM Aleksey Shipilev wrote: > On 10/01/2018 08:42 PM, David Karr wrote: > > I recently noticed some code in the codebase I work that looks like this > > (not with a hardcoded value): > > > > DecimalFormat df = new DecimalFormat("##0.00"); > > new BigDecimal(df.format(47.0)); > > > > I was pretty sure that was an inefficient way to do this, which I thought > > should be more like: > > > > new BigDecimal(47.0).setScale(2, BigDecimal.ROUND_HALF_UP); > > ... > > > I'd appreciate any help understanding why this is behaving oppositely of > > what I would expect. > > I think you need to start from JMH Samples: > > http://hg.openjdk.java.net/code-tools/jmh/file/tip/jmh-samples/src/main/java/org/openjdk/jmh/samples/ > > Notably JMHSample_08_DeadCode and JMHSample_35_Profilers. > Thanks. The deadcode pointer was critical. What was curious is that the original benchmark method was just newing up a single BigDecimal, even though it wasn't doing anything with it, and I think it's likely that result was accurate. When I added multiple news of BigDecimal, still not doing anything with them, that's apparently when the optimizer was apparently dropping the dead code. I tried a couple of variations of this, all returning the values being produced, so I'm reasonably confident the optimizer wasn't pruning anything. The stack profiler showed it calling the constructor, so it wasn't pruning it. > > -Aleksey > > >