From jbachorik at openjdk.org Tue Nov 1 08:24:21 2022 From: jbachorik at openjdk.org (Jaroslav Bachorik) Date: Tue, 1 Nov 2022 08:24:21 GMT Subject: RFR: 7950: Better DisjointBuilder performance for events not ordered by event end attribute In-Reply-To: References: Message-ID: On Sun, 30 Oct 2022 22:10:57 GMT, Richard Startin wrote: > When events are not disjoint and sorted by the end quantity, a lot of time can be spent in `DisjointBuilder.add`. Profiling shows that this is because of the linear search for the first lane ending before the added event starts, and then in the sort afterwards. > > This patch uses binary search to improve the handling of non-disjoint or non-sorted cases. It also adds checks whether the modification will disrupt descending order to avoid doing any work reordering the array. > > With a parameterised benchmark exercising some pathological cases: > > > import org.openjdk.jmc.common.item.IMemberAccessor; > import org.openjdk.jmc.common.unit.IQuantity; > import org.openjdk.jmc.common.unit.UnitLookup; > import org.openjdk.jmc.flightrecorder.internal.util.DisjointBuilder; > import org.openjdk.jmh.annotations.Benchmark; > import org.openjdk.jmh.annotations.Level; > 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 java.util.concurrent.ThreadLocalRandom; > > @State(Scope.Benchmark) > public class DisjointBuilderBenchmark { > > private static class RangeObject { > private final IQuantity start; > private final IQuantity end; > > RangeObject(IQuantity start, IQuantity end) { > this.start = start; > this.end = end; > } > > } > > private final static IMemberAccessor START = inObject -> inObject.start; > > private final static IMemberAccessor END = inObject -> inObject.end; > > public enum Scenario { > ASCENDING { > @Override > void fill(RangeObject[] rangeObjects) { > long min = 0; > long max = 1; > for (int i = 0; i < rangeObjects.length; i++) { > rangeObjects[i] = new RangeObject(UnitLookup.NUMBER_UNITY.quantity(min), > UnitLookup.NUMBER_UNITY.quantity(max)); > min++; > max++; > } > } > }, > DESCENDING { > @Override > void fill(RangeObject[] rangeObjects) { > long min = 2L * (rangeObjects.length - 1); > long max = 2L * rangeObjects.length - 1; > for (int i = 0; i < rangeObjects.length; i++) { > rangeObjects[i] = new RangeObject(UnitLookup.NUMBER_UNITY.quantity(min), > UnitLookup.NUMBER_UNITY.quantity(max)); > min--; > max--; > } > } > }, > SCRAMBLED { > @Override > void fill(RangeObject[] rangeObjects) { > ASCENDING.fill(rangeObjects); > shuffle(rangeObjects); > } > > private void shuffle(RangeObject[] data) { > for (int i = data.length; i > 1; i--) { > swap(data, i - 1, ThreadLocalRandom.current().nextInt(i)); > } > } > > private void swap(RangeObject[] arr, int i, int j) { > RangeObject tmp = arr[i]; > arr[i] = arr[j]; > arr[j] = tmp; > } > > }, > OVERLAPS { > @Override > void fill(RangeObject[] rangeObjects) { > long min = 0; > long max = 2; > for (int i = 0; i < rangeObjects.length; i++) { > rangeObjects[i] = new RangeObject(UnitLookup.NUMBER_UNITY.quantity(min), > UnitLookup.NUMBER_UNITY.quantity(max)); > min++; > max++; > } > } > }, > STACKED { > @Override > void fill(RangeObject[] rangeObjects) { > long min = 0; > long max = 2L * rangeObjects.length; > for (int i = 0; i < rangeObjects.length; i++) { > rangeObjects[i] = new RangeObject(UnitLookup.NUMBER_UNITY.quantity(min), > UnitLookup.NUMBER_UNITY.quantity(max)); > min++; > max--; > } > } > }, > SHALLOW_STACKS { > @Override > void fill(RangeObject[] rangeObjects) { > int stackDepth = 5; > long min = 0; > long max = 2 * stackDepth; > for (int i = 0; i < rangeObjects.length; i++) { > rangeObjects[i] = new RangeObject(UnitLookup.NUMBER_UNITY.quantity(min), > UnitLookup.NUMBER_UNITY.quantity(max)); > min++; > max--; > if (min == max) { > max += 2 * stackDepth; > } > } > } > }; > > abstract void fill(RangeObject[] rangeObjects); > } > > @Param({"ASCENDING", "DESCENDING", "SCRAMBLED", "OVERLAPS", "STACKED", "SHALLOW_STACKS"}) > Scenario scenario; > > @Param({"10000"}) > int numEvents; > private RangeObject[] input; > > @Setup(Level.Trial) > public void setup() { > input = new RangeObject[numEvents]; > scenario.fill(input); > } > > @Benchmark > public DisjointBuilder build() { > DisjointBuilder builder = new DisjointBuilder<>(START, END); > for (RangeObject rangeObject : input) { > builder.add(rangeObject); > } > return builder; > } > } > > > Good performance is maintained in the common ascending/disjoint case, but the degenerate cases perform much better: > > Before: > > Benchmark (numEvents) (scenario) Mode Cnt Score Error Units > DisjointBuilderBenchmark.build 10000 ASCENDING avgt 5 96.050 ? 1.240 us/op > DisjointBuilderBenchmark.build 10000 DESCENDING avgt 5 300246.685 ? 2101.505 us/op > DisjointBuilderBenchmark.build 10000 SCRAMBLED avgt 5 3977.733 ? 29.612 us/op > DisjointBuilderBenchmark.build 10000 OVERLAPS avgt 5 187.701 ? 6.161 us/op > DisjointBuilderBenchmark.build 10000 STACKED avgt 5 268306.481 ? 980.223 us/op > DisjointBuilderBenchmark.build 10000 SHALLOW_STACKS avgt 5 414.298 ? 5.719 us/op > > After: > > Benchmark (numEvents) (scenario) Mode Cnt Score Error Units > DisjointBuilderBenchmark.build 10000 ASCENDING avgt 5 91.583 ? 1.070 us/op > DisjointBuilderBenchmark.build 10000 DESCENDING avgt 5 608.281 ? 9.338 us/op > DisjointBuilderBenchmark.build 10000 SCRAMBLED avgt 5 596.601 ? 18.243 us/op > DisjointBuilderBenchmark.build 10000 OVERLAPS avgt 5 181.349 ? 1.012 us/op > DisjointBuilderBenchmark.build 10000 STACKED avgt 5 555.167 ? 13.316 us/op > DisjointBuilderBenchmark.build 10000 SHALLOW_STACKS avgt 5 353.700 ? 9.387 us/op Marked as reviewed by jbachorik (Author). ------------- PR: https://git.openjdk.org/jmc/pull/449 From duke at openjdk.org Tue Nov 1 13:08:47 2022 From: duke at openjdk.org (Richard Startin) Date: Tue, 1 Nov 2022 13:08:47 GMT Subject: RFR: 7944: Reduce allocations of Double during chunk loading [v2] In-Reply-To: References: Message-ID: <8kGjskwexw5Wwv1Dwr7fENX8opLwbx33eikgHopZ5VE=.2738b704-6660-40f7-afa2-b7206997a25d@github.com> On Thu, 27 Oct 2022 13:58:11 GMT, Richard Startin wrote: >> Using jmc-common as a library in a backend process we see high allocation rates of `Double` and have observed moderate performance improvements from this simple refactoring: >> * Use primitive `double` in `ImpreciseScaleFactor` >> * Use primitive `double` in `IScalarAffineTransformation.getOffset` >> * Push multiplication of a scale factor down to a new method `ScaleFactor.scale(long multiplier)` >> * Push `ScalarQuantity.in` down to `LongStored`/`DoubleStored` to avoid generalising over primitive types, when the `IQuantity` type can be varied instead. >> --------- >> ### Progress >> - [ ] Commit message must refer to an issue >> - [ ] Change must be properly reviewed (1 review required, with at least 1 [Committer](https://openjdk.org/bylaws#committer)) >> >> ### Reviewing >>
Using git >> >> Checkout this PR locally: \ >> `$ git fetch https://git.openjdk.org/jmc pull/436/head:pull/436` \ >> `$ git checkout pull/436` >> >> Update a local copy of the PR: \ >> `$ git checkout pull/436` \ >> `$ git pull https://git.openjdk.org/jmc pull/436/head` >> >>
>>
Using Skara CLI tools >> >> Checkout this PR locally: \ >> `$ git pr checkout 436` >> >> View PR using the GUI difftool: \ >> `$ git pr show -t 436` >> >>
>>
Using diff file >> >> Download this PR as a diff file: \ >> https://git.openjdk.org/jmc/pull/436.diff >> >>
> > Richard Startin has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains one commit: > > JMC-7944: Reduce allocations of Double during chunk loading Does this need more testing? The patch doesn't break compilation of any existing unit tests, can we be confident that higher level tests exercise and assert conditions which affected by this change? ------------- PR: https://git.openjdk.org/jmc/pull/436 From duke at openjdk.org Wed Nov 2 12:06:18 2022 From: duke at openjdk.org (duke) Date: Wed, 2 Nov 2022 12:06:18 GMT Subject: git: openjdk/jmc: Added tag 8.3.0-ga for changeset 7097ed26 Message-ID: <8654a351-647f-46f9-8f83-932795efdf39@openjdk.org> Tagged by: thegreystone Date: 2022-11-02 13:05:47 +0000 GA source release for JMC 8.3.0 Changeset: 7097ed26 Author: Marcus Hirt Date: 2022-10-13 18:18:43 +0000 URL: https://git.openjdk.org/jmc/commit/7097ed26ab4d04a691544aaf02f0ca12dc2db947 From bdutheil at openjdk.org Thu Nov 3 15:10:13 2022 From: bdutheil at openjdk.org (Brice Dutheil) Date: Thu, 3 Nov 2022 15:10:13 GMT Subject: RFR: 7879: Automated Analysis taking very long time to produce results for Class Leak Rule and showing wrong results. [v4] In-Reply-To: References: Message-ID: On Thu, 6 Oct 2022 20:28:14 GMT, Suchita Chaturvedi wrote: >> This PR takes care of optimizing and correcting the Class leak rule results on Automated Analysis Page. > > Suchita Chaturvedi has updated the pull request incrementally with one additional commit since the last revision: > > Adding higher timeout as default value I'm still not at ease there. I think contributing an actual test case for this rule (and/or the `DefaultIItemResultSet`) might beneficial. Having a synchronized block wrapping the `add(row)`, looks suspicious as this somehow coordinate threads but this behavior still non-determinist as it depends on how threads get scheduled. As per this [comment](https://github.com/openjdk/jmc/pull/419#issuecomment-1273226601) > To be more precise, by wrong results, I mean the size of data structure (I am trying printing while debugging) and the final top 5 results are not consistent. I do believe this happen due to the reason mentioned above. Maybe the resulting list needs to be sorted then ? core/org.openjdk.jmc.flightrecorder.rules.jdk/src/main/java/org/openjdk/jmc/flightrecorder/rules/jdk/util/DefaultIItemResultSet.java line 65: > 63: private final ArrayList data = new ArrayList<>(); > 64: private int cursor = -1; > 65: private ExecutorService exec; This could be final. core/org.openjdk.jmc.flightrecorder.rules.jdk/src/main/java/org/openjdk/jmc/flightrecorder/rules/jdk/util/DefaultIItemResultSet.java line 145: > 143: } > 144: if (Thread.currentThread().isInterrupted()) > 145: return; This `if` statement is irrelevant now, as it's the end of this function regardless the interruption status. ------------- PR: https://git.openjdk.org/jmc/pull/419 From clanger at openjdk.org Thu Nov 3 22:06:31 2022 From: clanger at openjdk.org (Christoph Langer) Date: Thu, 3 Nov 2022 22:06:31 GMT Subject: RFR: 7951: Factor out commonly used test helper classes from org.openjdk.jmc.common.test into dedicated test library module Message-ID: Triggered by an issue in project core/tests/org.openjdk.jmc.common.test, I came up with a little refactoring. So, org.openjdk.jmc.common.test is somewhat of a hybrid project. It contains both, some common test scaffolding classes plus some actual tests for the org.openjdk.jmc.common module. According to our special setup, which is not really like what maven would expect, we have all sources, also for the tests in the src/main/java folder. With a little tweak, that is specifying ${project.basedir}/src/main/java in the pom.xml, we can direct maven to consume the tests from there instead of the usually expected src/test/java subfolder. However, when updating the eclipse project configuration from that pom.xml, the project would not export the test helper classes to other modules within eclipse any more. I'm hereby factoring out the test helper classes into a new module called core/tests/org.openjdk.jmc.testlib. This module will then only serve as a test helper library but not contain any actual tests. Furthermore I include some other cleanups in project and manifest files, e.g. removal of .settings files which are .gitignored because they would be generated when importing the JMC projects into Eclipse. ------------- Commit messages: - JMC-7951 Changes: https://git.openjdk.org/jmc/pull/451/files Webrev: https://webrevs.openjdk.org/?repo=jmc&pr=451&range=00 Issue: https://bugs.openjdk.org/browse/JMC-7951 Stats: 920 lines in 102 files changed: 195 ins; 368 del; 357 mod Patch: https://git.openjdk.org/jmc/pull/451.diff Fetch: git fetch https://git.openjdk.org/jmc pull/451/head:pull/451 PR: https://git.openjdk.org/jmc/pull/451 From duke at openjdk.org Sat Nov 5 20:32:59 2022 From: duke at openjdk.org (Martin Skarsaune) Date: Sat, 5 Nov 2022 20:32:59 GMT Subject: RFR: 7455: Add support for jolokia JMX service connection [v27] In-Reply-To: References: Message-ID: > Setting back for review. The azure problem requires a fix in Jolokia. > > Make use of support for JMX service connection in jolokia 1.7.0 and later to connect to JVMs over this protocol. Martin Skarsaune has updated the pull request incrementally with three additional commits since the last revision: - JMC-7455: No longer rely on selflink (as in https://github.com/rhuss/jolokia/pull/489) - JMC-7455: Handle credentials not yet present - JMC-7455: Cosmetic: Undo formatting of copyright that got messed up ------------- Changes: - all: https://git.openjdk.org/jmc/pull/332/files - new: https://git.openjdk.org/jmc/pull/332/files/f8492788..4ed92653 Webrevs: - full: https://webrevs.openjdk.org/?repo=jmc&pr=332&range=26 - incr: https://webrevs.openjdk.org/?repo=jmc&pr=332&range=25-26 Stats: 70 lines in 3 files changed: 19 ins; 2 del; 49 mod Patch: https://git.openjdk.org/jmc/pull/332.diff Fetch: git fetch https://git.openjdk.org/jmc pull/332/head:pull/332 PR: https://git.openjdk.org/jmc/pull/332 From egahlin at openjdk.org Wed Nov 9 09:58:06 2022 From: egahlin at openjdk.org (Erik Gahlin) Date: Wed, 9 Nov 2022 09:58:06 GMT Subject: RFR: 7950: Better DisjointBuilder performance for events not ordered by event end attribute In-Reply-To: References: Message-ID: On Sun, 30 Oct 2022 22:10:57 GMT, Richard Startin wrote: > When events are not disjoint and sorted by the end quantity, a lot of time can be spent in `DisjointBuilder.add`. Profiling shows that this is because of the linear search for the first lane ending before the added event starts, and then in the sort afterwards. > > This patch uses binary search to improve the handling of non-disjoint or non-sorted cases. It also adds checks whether the modification will disrupt descending order to avoid doing any work reordering the array. > > With a parameterised benchmark exercising some pathological cases: > > > import org.openjdk.jmc.common.item.IMemberAccessor; > import org.openjdk.jmc.common.unit.IQuantity; > import org.openjdk.jmc.common.unit.UnitLookup; > import org.openjdk.jmc.flightrecorder.internal.util.DisjointBuilder; > import org.openjdk.jmh.annotations.Benchmark; > import org.openjdk.jmh.annotations.Level; > 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 java.util.concurrent.ThreadLocalRandom; > > @State(Scope.Benchmark) > public class DisjointBuilderBenchmark { > > private static class RangeObject { > private final IQuantity start; > private final IQuantity end; > > RangeObject(IQuantity start, IQuantity end) { > this.start = start; > this.end = end; > } > > } > > private final static IMemberAccessor START = inObject -> inObject.start; > > private final static IMemberAccessor END = inObject -> inObject.end; > > public enum Scenario { > ASCENDING { > @Override > void fill(RangeObject[] rangeObjects) { > long min = 0; > long max = 1; > for (int i = 0; i < rangeObjects.length; i++) { > rangeObjects[i] = new RangeObject(UnitLookup.NUMBER_UNITY.quantity(min), > UnitLookup.NUMBER_UNITY.quantity(max)); > min++; > max++; > } > } > }, > DESCENDING { > @Override > void fill(RangeObject[] rangeObjects) { > long min = 2L * (rangeObjects.length - 1); > long max = 2L * rangeObjects.length - 1; > for (int i = 0; i < rangeObjects.length; i++) { > rangeObjects[i] = new RangeObject(UnitLookup.NUMBER_UNITY.quantity(min), > UnitLookup.NUMBER_UNITY.quantity(max)); > min--; > max--; > } > } > }, > SCRAMBLED { > @Override > void fill(RangeObject[] rangeObjects) { > ASCENDING.fill(rangeObjects); > shuffle(rangeObjects); > } > > private void shuffle(RangeObject[] data) { > for (int i = data.length; i > 1; i--) { > swap(data, i - 1, ThreadLocalRandom.current().nextInt(i)); > } > } > > private void swap(RangeObject[] arr, int i, int j) { > RangeObject tmp = arr[i]; > arr[i] = arr[j]; > arr[j] = tmp; > } > > }, > OVERLAPS { > @Override > void fill(RangeObject[] rangeObjects) { > long min = 0; > long max = 2; > for (int i = 0; i < rangeObjects.length; i++) { > rangeObjects[i] = new RangeObject(UnitLookup.NUMBER_UNITY.quantity(min), > UnitLookup.NUMBER_UNITY.quantity(max)); > min++; > max++; > } > } > }, > STACKED { > @Override > void fill(RangeObject[] rangeObjects) { > long min = 0; > long max = 2L * rangeObjects.length; > for (int i = 0; i < rangeObjects.length; i++) { > rangeObjects[i] = new RangeObject(UnitLookup.NUMBER_UNITY.quantity(min), > UnitLookup.NUMBER_UNITY.quantity(max)); > min++; > max--; > } > } > }, > SHALLOW_STACKS { > @Override > void fill(RangeObject[] rangeObjects) { > int stackDepth = 5; > long min = 0; > long max = 2 * stackDepth; > for (int i = 0; i < rangeObjects.length; i++) { > rangeObjects[i] = new RangeObject(UnitLookup.NUMBER_UNITY.quantity(min), > UnitLookup.NUMBER_UNITY.quantity(max)); > min++; > max--; > if (min == max) { > max += 2 * stackDepth; > } > } > } > }; > > abstract void fill(RangeObject[] rangeObjects); > } > > @Param({"ASCENDING", "DESCENDING", "SCRAMBLED", "OVERLAPS", "STACKED", "SHALLOW_STACKS"}) > Scenario scenario; > > @Param({"10000"}) > int numEvents; > private RangeObject[] input; > > @Setup(Level.Trial) > public void setup() { > input = new RangeObject[numEvents]; > scenario.fill(input); > } > > @Benchmark > public DisjointBuilder build() { > DisjointBuilder builder = new DisjointBuilder<>(START, END); > for (RangeObject rangeObject : input) { > builder.add(rangeObject); > } > return builder; > } > } > > > Good performance is maintained in the common ascending/disjoint case, but the degenerate cases perform much better: > > Before: > > Benchmark (numEvents) (scenario) Mode Cnt Score Error Units > DisjointBuilderBenchmark.build 10000 ASCENDING avgt 5 96.050 ? 1.240 us/op > DisjointBuilderBenchmark.build 10000 DESCENDING avgt 5 300246.685 ? 2101.505 us/op > DisjointBuilderBenchmark.build 10000 SCRAMBLED avgt 5 3977.733 ? 29.612 us/op > DisjointBuilderBenchmark.build 10000 OVERLAPS avgt 5 187.701 ? 6.161 us/op > DisjointBuilderBenchmark.build 10000 STACKED avgt 5 268306.481 ? 980.223 us/op > DisjointBuilderBenchmark.build 10000 SHALLOW_STACKS avgt 5 414.298 ? 5.719 us/op > > After: > > Benchmark (numEvents) (scenario) Mode Cnt Score Error Units > DisjointBuilderBenchmark.build 10000 ASCENDING avgt 5 91.583 ? 1.070 us/op > DisjointBuilderBenchmark.build 10000 DESCENDING avgt 5 608.281 ? 9.338 us/op > DisjointBuilderBenchmark.build 10000 SCRAMBLED avgt 5 596.601 ? 18.243 us/op > DisjointBuilderBenchmark.build 10000 OVERLAPS avgt 5 181.349 ? 1.012 us/op > DisjointBuilderBenchmark.build 10000 STACKED avgt 5 555.167 ? 13.316 us/op > DisjointBuilderBenchmark.build 10000 SHALLOW_STACKS avgt 5 353.700 ? 9.387 us/op When I wrote the original code in 2010 collisions were rare. I think I saw a few cases of 2-3 lanes (for the same event type and thread), typically when doing recursive events. I wonder what has changed, if this is no longer a case? The JVM usually doesn't write overlapping events. Is it thread buffers coming out of order? ------------- PR: https://git.openjdk.org/jmc/pull/449 From duke at openjdk.org Wed Nov 9 10:39:32 2022 From: duke at openjdk.org (Richard Startin) Date: Wed, 9 Nov 2022 10:39:32 GMT Subject: RFR: 7950: Better DisjointBuilder performance for events not ordered by event end attribute In-Reply-To: References: Message-ID: On Wed, 9 Nov 2022 09:51:49 GMT, Erik Gahlin wrote: > When I wrote the original code in 2010 collisions were rare. I think I saw a few cases of 2-3 lanes (for the same event type and thread), typically when doing recursive events. I wonder what has changed, if this is no longer a case? The JVM usually doesn't write overlapping events. Is it thread buffers coming out of order? In our use case this method gets very hot sporadically throughout the day and it depends on the recordings. This tends to show up with custom JFR events which can be committed in any order, but I believe @Gunde has some pathological profiles with only built in events. Having spoken to @Gunde internally, the worst case behaviour behaviour of this method is a "known issue" but we're also aware that the one-lane optimisation is very effective for the majority of JFR profiles, so it's important not to regress on common cases. ------------- PR: https://git.openjdk.org/jmc/pull/449 From hdafgard at openjdk.org Wed Nov 9 16:08:36 2022 From: hdafgard at openjdk.org (Henrik =?UTF-8?B?RGFmZ8OlcmQ=?=) Date: Wed, 9 Nov 2022 16:08:36 GMT Subject: RFR: 7950: Better DisjointBuilder performance for events not ordered by event end attribute In-Reply-To: References: Message-ID: On Wed, 9 Nov 2022 10:36:08 GMT, Richard Startin wrote: > When I wrote the original code in 2010 collisions were rare. I think I saw a few cases of 2-3 lanes (for the same event type and thread), typically when doing recursive events. I wonder what has changed, if this is no longer a case? The JVM usually doesn't write overlapping events. Is it thread buffers coming out of order? @egahlin As far as I've investigated the issue is prevalent in JVM applications running with Amazon Kinesis. It can produce tens of thousands of overlapping File Read events. ------------- PR: https://git.openjdk.org/jmc/pull/449 From egahlin at openjdk.org Wed Nov 9 18:06:01 2022 From: egahlin at openjdk.org (Erik Gahlin) Date: Wed, 9 Nov 2022 18:06:01 GMT Subject: RFR: 7950: Better DisjointBuilder performance for events not ordered by event end attribute In-Reply-To: References: Message-ID: On Wed, 9 Nov 2022 16:04:57 GMT, Henrik Dafg?rd wrote: > > When I wrote the original code in 2010 collisions were rare. I think I saw a few cases of 2-3 lanes (for the same event type and thread), typically when doing recursive events. I wonder what has changed, if this is no longer a case? The JVM usually doesn't write overlapping events. Is it thread buffers coming out of order? > > @egahlin As far as I've investigated the issue is prevalent in JVM applications running with Amazon Kinesis. It can produce tens of thousands of overlapping File Read events. Interesting. I took a look at the FileRead events in the JDK I think I found a bug that could explain the issue: try { start = EventConfiguration.timestamp(); write(b); bytesWritten = b.length; } finally { long duration = EventConfiguration.timestamp(); if (eventConfiguration.shouldCommit(duration)) { FileWriteEvent.commit(start, duration, path, bytesWritten); } } It should be: long duration = EventConfiguration.timestamp() - start; This regression was introduced in JDK 15. I will prepare a fix. Should be backported. https://hg.openjdk.java.net/jdk/jdk/rev/dd0caf00b05c The fix to JMC still makes sense. ------------- PR: https://git.openjdk.org/jmc/pull/449 From duke at openjdk.org Wed Nov 9 22:54:36 2022 From: duke at openjdk.org (Richard Startin) Date: Wed, 9 Nov 2022 22:54:36 GMT Subject: Integrated: 7944: Reduce allocations of Double during chunk loading In-Reply-To: References: Message-ID: On Sat, 8 Oct 2022 17:30:35 GMT, Richard Startin wrote: > Using jmc-common as a library in a backend process we see high allocation rates of `Double` and have observed moderate performance improvements from this simple refactoring: > * Use primitive `double` in `ImpreciseScaleFactor` > * Use primitive `double` in `IScalarAffineTransformation.getOffset` > * Push multiplication of a scale factor down to a new method `ScaleFactor.scale(long multiplier)` > * Push `ScalarQuantity.in` down to `LongStored`/`DoubleStored` to avoid generalising over primitive types, when the `IQuantity` type can be varied instead. > --------- > ### Progress > - [ ] Commit message must refer to an issue > - [ ] Change must be properly reviewed (1 review required, with at least 1 [Committer](https://openjdk.org/bylaws#committer)) > > ### Reviewing >
Using git > > Checkout this PR locally: \ > `$ git fetch https://git.openjdk.org/jmc pull/436/head:pull/436` \ > `$ git checkout pull/436` > > Update a local copy of the PR: \ > `$ git checkout pull/436` \ > `$ git pull https://git.openjdk.org/jmc pull/436/head` > >
>
Using Skara CLI tools > > Checkout this PR locally: \ > `$ git pr checkout 436` > > View PR using the GUI difftool: \ > `$ git pr show -t 436` > >
>
Using diff file > > Download this PR as a diff file: \ > https://git.openjdk.org/jmc/pull/436.diff > >
This pull request has now been integrated. Changeset: 761797e6 Author: Richard Startin Committer: Henrik Dafg?rd URL: https://git.openjdk.org/jmc/commit/761797e6990e3588331250a41695b4ba978eba90 Stats: 103 lines in 10 files changed: 47 ins; 28 del; 28 mod 7944: Reduce allocations of Double during chunk loading Reviewed-by: hdafgard ------------- PR: https://git.openjdk.org/jmc/pull/436 From duke at openjdk.org Thu Nov 10 09:33:22 2022 From: duke at openjdk.org (Richard Startin) Date: Thu, 10 Nov 2022 09:33:22 GMT Subject: RFR: 7950: Better DisjointBuilder performance for events not ordered by event end attribute Message-ID: 7950: Better DisjointBuilder performance for events not ordered by event end attribute ------------- Commit messages: - 7950: Better DisjointBuilder performance for events not ordered by event end attribute Changes: https://git.openjdk.org/jmc/pull/450/files Webrev: https://webrevs.openjdk.org/?repo=jmc&pr=450&range=00 Issue: https://bugs.openjdk.org/browse/JMC-7950 Stats: 230 lines in 10 files changed: 82 ins; 133 del; 15 mod Patch: https://git.openjdk.org/jmc/pull/450.diff Fetch: git fetch https://git.openjdk.org/jmc pull/450/head:pull/450 PR: https://git.openjdk.org/jmc/pull/450 From duke at openjdk.org Thu Nov 10 11:07:15 2022 From: duke at openjdk.org (Richard Startin) Date: Thu, 10 Nov 2022 11:07:15 GMT Subject: RFR: 7975: Restructure data in affine transform classes [v2] In-Reply-To: References: Message-ID: <4KKx5mAHaBIM6P0wXi5Y_L49mY6Gp4i6-H-76ykYno4=.d4067ca6-3854-4fb8-8b71-8eff480fad63@github.com> > 7975: Restructure data in affine transform classes Richard Startin 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: 7975: Restructure data in affine transform classes ------------- Changes: - all: https://git.openjdk.org/jmc/pull/450/files - new: https://git.openjdk.org/jmc/pull/450/files/6331adc3..73548a64 Webrevs: - full: https://webrevs.openjdk.org/?repo=jmc&pr=450&range=01 - incr: https://webrevs.openjdk.org/?repo=jmc&pr=450&range=00-01 Stats: 0 lines in 0 files changed: 0 ins; 0 del; 0 mod Patch: https://git.openjdk.org/jmc/pull/450.diff Fetch: git fetch https://git.openjdk.org/jmc pull/450/head:pull/450 PR: https://git.openjdk.org/jmc/pull/450 From schaturvedi at openjdk.org Fri Nov 11 11:42:55 2022 From: schaturvedi at openjdk.org (Suchita Chaturvedi) Date: Fri, 11 Nov 2022 11:42:55 GMT Subject: RFR: 7879: Automated Analysis taking very long time to produce results for Class Leak Rule and showing wrong results. [v5] In-Reply-To: References: Message-ID: > This PR takes care of optimizing and correcting the Class leak rule results on Automated Analysis Page. Suchita Chaturvedi has updated the pull request incrementally with one additional commit since the last revision: Implemented minor review comments ------------- Changes: - all: https://git.openjdk.org/jmc/pull/419/files - new: https://git.openjdk.org/jmc/pull/419/files/9876fd12..4206f70c Webrevs: - full: https://webrevs.openjdk.org/?repo=jmc&pr=419&range=04 - incr: https://webrevs.openjdk.org/?repo=jmc&pr=419&range=03-04 Stats: 5 lines in 1 file changed: 1 ins; 3 del; 1 mod Patch: https://git.openjdk.org/jmc/pull/419.diff Fetch: git fetch https://git.openjdk.org/jmc pull/419/head:pull/419 PR: https://git.openjdk.org/jmc/pull/419 From schaturvedi at openjdk.org Fri Nov 11 12:09:35 2022 From: schaturvedi at openjdk.org (Suchita Chaturvedi) Date: Fri, 11 Nov 2022 12:09:35 GMT Subject: RFR: 7879: Automated Analysis taking very long time to produce results for Class Leak Rule and showing wrong results. [v4] In-Reply-To: References: Message-ID: On Mon, 24 Oct 2022 13:46:44 GMT, Alex Macdonald wrote: >> Suchita Chaturvedi has updated the pull request incrementally with one additional commit since the last revision: >> >> Adding higher timeout as default value > > I think it looks okay for me. It would be nice to have a way of reproducing the issue to verify, but I get it's tough if the original jfr is from a customer and can't be shared. > > Having said that, @Gunde and @bric3 did substantial review on this PR as well as the previous (https://github.com/openjdk/jmc/pull/248), and while on the surface it looks like everything has been addressed I would feel much more comfortable if they could just confirm that what they wanted addressed was updated in this PR before merging it. @aptmac @bric3 I have implemented the review comments suggested. @bric3 Yes, you are right " In DefaultIItemResultSet the insertion in data order is dependent on the iteration order of the aggregate collection, since it's a set, there's no ordering guarantees. " We are just processing the records in DefaultIItemResultSet. Sorting is taken care in ClassLeakingRule.java class at line no 182 ( entries.sort(null); ) after all the records are processed. The reason for why wrong records were shown previously was : We were showing the results in ascending order of the count i.e. difference between the number of times classed loaded vs unloaded. Whereas we had to show in descending order. For Ex: There are 10 classes A (0), B (1), C (1)........H (55), I (60), J (75). As per current implementation we are showing A, B, C on class leak rule results on Automated Analysis Screen and saying everything is normal. Whereas, we have to show J, I, H classes because they are loaded without being unloaded and they need attention. So JMC has to show warning instead of showing OK results. Regarding test case, we already have a JFRRuleBaseline.xml for testing rules and their results and I have updated that as part of this PR. ------------- PR: https://git.openjdk.org/jmc/pull/419 From duke at openjdk.org Mon Nov 14 11:04:38 2022 From: duke at openjdk.org (Richard Startin) Date: Mon, 14 Nov 2022 11:04:38 GMT Subject: RFR: 7975: Restructure data in affine transform classes [v2] In-Reply-To: <4KKx5mAHaBIM6P0wXi5Y_L49mY6Gp4i6-H-76ykYno4=.d4067ca6-3854-4fb8-8b71-8eff480fad63@github.com> References: <4KKx5mAHaBIM6P0wXi5Y_L49mY6Gp4i6-H-76ykYno4=.d4067ca6-3854-4fb8-8b71-8eff480fad63@github.com> Message-ID: On Thu, 10 Nov 2022 11:07:15 GMT, Richard Startin wrote: >> 7975: Restructure data in affine transform classes > > Richard Startin 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: > > 7975: Restructure data in affine transform classes This didn't turn out to be as effective as hoped ------------- PR: https://git.openjdk.org/jmc/pull/450 From duke at openjdk.org Mon Nov 14 11:04:39 2022 From: duke at openjdk.org (Richard Startin) Date: Mon, 14 Nov 2022 11:04:39 GMT Subject: Withdrawn: 7975: Restructure data in affine transform classes In-Reply-To: References: Message-ID: <9RGbRlSjTofT7jngCBiSdETh1DMn4aUDGcSB29nG0qs=.be0b4c80-a851-437c-95d1-35d3bb47ba43@github.com> On Tue, 1 Nov 2022 21:01:09 GMT, Richard Startin wrote: > 7975: Restructure data in affine transform classes This pull request has been closed without being integrated. ------------- PR: https://git.openjdk.org/jmc/pull/450 From jpbempel at openjdk.org Wed Nov 16 13:35:02 2022 From: jpbempel at openjdk.org (Jean-Philippe Bempel) Date: Wed, 16 Nov 2022 13:35:02 GMT Subject: RFR: 7977: Maximum Young Gen Size is displaying the min in GC config Page Message-ID: <-PAa0dk5ngVkj_h_UaLRnwMvDyOI_u7y9WI_j3RySAc=.7a88933f-b361-4670-a45f-e6146e94d234@github.com> Change min to max attribute ------------- Commit messages: - 7977: Maximum Young Gen Size is displaying the min in GC config Page Changes: https://git.openjdk.org/jmc/pull/452/files Webrev: https://webrevs.openjdk.org/?repo=jmc&pr=452&range=00 Issue: https://bugs.openjdk.org/browse/JMC-7977 Stats: 1 line in 1 file changed: 0 ins; 0 del; 1 mod Patch: https://git.openjdk.org/jmc/pull/452.diff Fetch: git fetch https://git.openjdk.org/jmc pull/452/head:pull/452 PR: https://git.openjdk.org/jmc/pull/452 From aptmac at openjdk.org Wed Nov 16 22:17:04 2022 From: aptmac at openjdk.org (Alex Macdonald) Date: Wed, 16 Nov 2022 22:17:04 GMT Subject: RFR: 7977: Maximum Young Gen Size is displaying the min in GC config Page In-Reply-To: <-PAa0dk5ngVkj_h_UaLRnwMvDyOI_u7y9WI_j3RySAc=.7a88933f-b361-4670-a45f-e6146e94d234@github.com> References: <-PAa0dk5ngVkj_h_UaLRnwMvDyOI_u7y9WI_j3RySAc=.7a88933f-b361-4670-a45f-e6146e94d234@github.com> Message-ID: On Wed, 16 Nov 2022 13:27:07 GMT, Jean-Philippe Bempel wrote: > Change min to max attribute Marked as reviewed by aptmac (Reviewer). ------------- PR: https://git.openjdk.org/jmc/pull/452 From jpbempel at openjdk.org Thu Nov 17 06:51:29 2022 From: jpbempel at openjdk.org (Jean-Philippe Bempel) Date: Thu, 17 Nov 2022 06:51:29 GMT Subject: RFR: 7977: Maximum Young Gen Size is displaying the min in GC config Page [v2] In-Reply-To: <-PAa0dk5ngVkj_h_UaLRnwMvDyOI_u7y9WI_j3RySAc=.7a88933f-b361-4670-a45f-e6146e94d234@github.com> References: <-PAa0dk5ngVkj_h_UaLRnwMvDyOI_u7y9WI_j3RySAc=.7a88933f-b361-4670-a45f-e6146e94d234@github.com> Message-ID: > Change min to max attribute Jean-Philippe Bempel has updated the pull request incrementally with one additional commit since the last revision: update copyright year ------------- Changes: - all: https://git.openjdk.org/jmc/pull/452/files - new: https://git.openjdk.org/jmc/pull/452/files/6450acdc..a3852415 Webrevs: - full: https://webrevs.openjdk.org/?repo=jmc&pr=452&range=01 - incr: https://webrevs.openjdk.org/?repo=jmc&pr=452&range=00-01 Stats: 1 line in 1 file changed: 0 ins; 0 del; 1 mod Patch: https://git.openjdk.org/jmc/pull/452.diff Fetch: git fetch https://git.openjdk.org/jmc pull/452/head:pull/452 PR: https://git.openjdk.org/jmc/pull/452 From jpbempel at openjdk.org Fri Nov 18 08:22:29 2022 From: jpbempel at openjdk.org (Jean-Philippe Bempel) Date: Fri, 18 Nov 2022 08:22:29 GMT Subject: Integrated: 7977: Maximum Young Gen Size is displaying the min in GC config Page In-Reply-To: <-PAa0dk5ngVkj_h_UaLRnwMvDyOI_u7y9WI_j3RySAc=.7a88933f-b361-4670-a45f-e6146e94d234@github.com> References: <-PAa0dk5ngVkj_h_UaLRnwMvDyOI_u7y9WI_j3RySAc=.7a88933f-b361-4670-a45f-e6146e94d234@github.com> Message-ID: On Wed, 16 Nov 2022 13:27:07 GMT, Jean-Philippe Bempel wrote: > Change min to max attribute This pull request has now been integrated. Changeset: 9ba238e1 Author: Jean-Philippe Bempel URL: https://git.openjdk.org/jmc/commit/9ba238e15cf61298a724442e3039e3f249e23798 Stats: 2 lines in 1 file changed: 0 ins; 0 del; 2 mod 7977: Maximum Young Gen Size is displaying the min in GC config Page Reviewed-by: aptmac ------------- PR: https://git.openjdk.org/jmc/pull/452 From hdafgard at openjdk.org Sat Nov 19 03:16:22 2022 From: hdafgard at openjdk.org (Henrik =?UTF-8?B?RGFmZ8OlcmQ=?=) Date: Sat, 19 Nov 2022 03:16:22 GMT Subject: RFR: 7950: Better DisjointBuilder performance for events not ordered by event end attribute In-Reply-To: References: Message-ID: On Sun, 30 Oct 2022 22:10:57 GMT, Richard Startin wrote: > When events are not disjoint and sorted by the end quantity, a lot of time can be spent in `DisjointBuilder.add`. Profiling shows that this is because of the linear search for the first lane ending before the added event starts, and then in the sort afterwards. > > This patch uses binary search to improve the handling of non-disjoint or non-sorted cases. It also adds checks whether the modification will disrupt descending order to avoid doing any work reordering the array. > > With a parameterised benchmark exercising some pathological cases: > > > import org.openjdk.jmc.common.item.IMemberAccessor; > import org.openjdk.jmc.common.unit.IQuantity; > import org.openjdk.jmc.common.unit.UnitLookup; > import org.openjdk.jmc.flightrecorder.internal.util.DisjointBuilder; > import org.openjdk.jmh.annotations.Benchmark; > import org.openjdk.jmh.annotations.Level; > 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 java.util.concurrent.ThreadLocalRandom; > > @State(Scope.Benchmark) > public class DisjointBuilderBenchmark { > > private static class RangeObject { > private final IQuantity start; > private final IQuantity end; > > RangeObject(IQuantity start, IQuantity end) { > this.start = start; > this.end = end; > } > > } > > private final static IMemberAccessor START = inObject -> inObject.start; > > private final static IMemberAccessor END = inObject -> inObject.end; > > public enum Scenario { > ASCENDING { > @Override > void fill(RangeObject[] rangeObjects) { > long min = 0; > long max = 1; > for (int i = 0; i < rangeObjects.length; i++) { > rangeObjects[i] = new RangeObject(UnitLookup.NUMBER_UNITY.quantity(min), > UnitLookup.NUMBER_UNITY.quantity(max)); > min++; > max++; > } > } > }, > DESCENDING { > @Override > void fill(RangeObject[] rangeObjects) { > long min = 2L * (rangeObjects.length - 1); > long max = 2L * rangeObjects.length - 1; > for (int i = 0; i < rangeObjects.length; i++) { > rangeObjects[i] = new RangeObject(UnitLookup.NUMBER_UNITY.quantity(min), > UnitLookup.NUMBER_UNITY.quantity(max)); > min--; > max--; > } > } > }, > SCRAMBLED { > @Override > void fill(RangeObject[] rangeObjects) { > ASCENDING.fill(rangeObjects); > shuffle(rangeObjects); > } > > private void shuffle(RangeObject[] data) { > for (int i = data.length; i > 1; i--) { > swap(data, i - 1, ThreadLocalRandom.current().nextInt(i)); > } > } > > private void swap(RangeObject[] arr, int i, int j) { > RangeObject tmp = arr[i]; > arr[i] = arr[j]; > arr[j] = tmp; > } > > }, > OVERLAPS { > @Override > void fill(RangeObject[] rangeObjects) { > long min = 0; > long max = 2; > for (int i = 0; i < rangeObjects.length; i++) { > rangeObjects[i] = new RangeObject(UnitLookup.NUMBER_UNITY.quantity(min), > UnitLookup.NUMBER_UNITY.quantity(max)); > min++; > max++; > } > } > }, > STACKED { > @Override > void fill(RangeObject[] rangeObjects) { > long min = 0; > long max = 2L * rangeObjects.length; > for (int i = 0; i < rangeObjects.length; i++) { > rangeObjects[i] = new RangeObject(UnitLookup.NUMBER_UNITY.quantity(min), > UnitLookup.NUMBER_UNITY.quantity(max)); > min++; > max--; > } > } > }, > SHALLOW_STACKS { > @Override > void fill(RangeObject[] rangeObjects) { > int stackDepth = 5; > long min = 0; > long max = 2 * stackDepth; > for (int i = 0; i < rangeObjects.length; i++) { > rangeObjects[i] = new RangeObject(UnitLookup.NUMBER_UNITY.quantity(min), > UnitLookup.NUMBER_UNITY.quantity(max)); > min++; > max--; > if (min == max) { > max += 2 * stackDepth; > } > } > } > }; > > abstract void fill(RangeObject[] rangeObjects); > } > > @Param({"ASCENDING", "DESCENDING", "SCRAMBLED", "OVERLAPS", "STACKED", "SHALLOW_STACKS"}) > Scenario scenario; > > @Param({"10000"}) > int numEvents; > private RangeObject[] input; > > @Setup(Level.Trial) > public void setup() { > input = new RangeObject[numEvents]; > scenario.fill(input); > } > > @Benchmark > public DisjointBuilder build() { > DisjointBuilder builder = new DisjointBuilder<>(START, END); > for (RangeObject rangeObject : input) { > builder.add(rangeObject); > } > return builder; > } > } > > > Good performance is maintained in the common ascending/disjoint case, but the degenerate cases perform much better: > > Before: > > Benchmark (numEvents) (scenario) Mode Cnt Score Error Units > DisjointBuilderBenchmark.build 10000 ASCENDING avgt 5 96.050 ? 1.240 us/op > DisjointBuilderBenchmark.build 10000 DESCENDING avgt 5 300246.685 ? 2101.505 us/op > DisjointBuilderBenchmark.build 10000 SCRAMBLED avgt 5 3977.733 ? 29.612 us/op > DisjointBuilderBenchmark.build 10000 OVERLAPS avgt 5 187.701 ? 6.161 us/op > DisjointBuilderBenchmark.build 10000 STACKED avgt 5 268306.481 ? 980.223 us/op > DisjointBuilderBenchmark.build 10000 SHALLOW_STACKS avgt 5 414.298 ? 5.719 us/op > > After: > > Benchmark (numEvents) (scenario) Mode Cnt Score Error Units > DisjointBuilderBenchmark.build 10000 ASCENDING avgt 5 91.583 ? 1.070 us/op > DisjointBuilderBenchmark.build 10000 DESCENDING avgt 5 608.281 ? 9.338 us/op > DisjointBuilderBenchmark.build 10000 SCRAMBLED avgt 5 596.601 ? 18.243 us/op > DisjointBuilderBenchmark.build 10000 OVERLAPS avgt 5 181.349 ? 1.012 us/op > DisjointBuilderBenchmark.build 10000 STACKED avgt 5 555.167 ? 13.316 us/op > DisjointBuilderBenchmark.build 10000 SHALLOW_STACKS avgt 5 353.700 ? 9.387 us/op Marked as reviewed by hdafgard (Reviewer). ------------- PR: https://git.openjdk.org/jmc/pull/449 From duke at openjdk.org Sat Nov 19 15:02:54 2022 From: duke at openjdk.org (Richard Startin) Date: Sat, 19 Nov 2022 15:02:54 GMT Subject: Integrated: 7950: Better DisjointBuilder performance for events not ordered by event end attribute In-Reply-To: References: Message-ID: On Sun, 30 Oct 2022 22:10:57 GMT, Richard Startin wrote: > When events are not disjoint and sorted by the end quantity, a lot of time can be spent in `DisjointBuilder.add`. Profiling shows that this is because of the linear search for the first lane ending before the added event starts, and then in the sort afterwards. > > This patch uses binary search to improve the handling of non-disjoint or non-sorted cases. It also adds checks whether the modification will disrupt descending order to avoid doing any work reordering the array. > > With a parameterised benchmark exercising some pathological cases: > > > import org.openjdk.jmc.common.item.IMemberAccessor; > import org.openjdk.jmc.common.unit.IQuantity; > import org.openjdk.jmc.common.unit.UnitLookup; > import org.openjdk.jmc.flightrecorder.internal.util.DisjointBuilder; > import org.openjdk.jmh.annotations.Benchmark; > import org.openjdk.jmh.annotations.Level; > 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 java.util.concurrent.ThreadLocalRandom; > > @State(Scope.Benchmark) > public class DisjointBuilderBenchmark { > > private static class RangeObject { > private final IQuantity start; > private final IQuantity end; > > RangeObject(IQuantity start, IQuantity end) { > this.start = start; > this.end = end; > } > > } > > private final static IMemberAccessor START = inObject -> inObject.start; > > private final static IMemberAccessor END = inObject -> inObject.end; > > public enum Scenario { > ASCENDING { > @Override > void fill(RangeObject[] rangeObjects) { > long min = 0; > long max = 1; > for (int i = 0; i < rangeObjects.length; i++) { > rangeObjects[i] = new RangeObject(UnitLookup.NUMBER_UNITY.quantity(min), > UnitLookup.NUMBER_UNITY.quantity(max)); > min++; > max++; > } > } > }, > DESCENDING { > @Override > void fill(RangeObject[] rangeObjects) { > long min = 2L * (rangeObjects.length - 1); > long max = 2L * rangeObjects.length - 1; > for (int i = 0; i < rangeObjects.length; i++) { > rangeObjects[i] = new RangeObject(UnitLookup.NUMBER_UNITY.quantity(min), > UnitLookup.NUMBER_UNITY.quantity(max)); > min--; > max--; > } > } > }, > SCRAMBLED { > @Override > void fill(RangeObject[] rangeObjects) { > ASCENDING.fill(rangeObjects); > shuffle(rangeObjects); > } > > private void shuffle(RangeObject[] data) { > for (int i = data.length; i > 1; i--) { > swap(data, i - 1, ThreadLocalRandom.current().nextInt(i)); > } > } > > private void swap(RangeObject[] arr, int i, int j) { > RangeObject tmp = arr[i]; > arr[i] = arr[j]; > arr[j] = tmp; > } > > }, > OVERLAPS { > @Override > void fill(RangeObject[] rangeObjects) { > long min = 0; > long max = 2; > for (int i = 0; i < rangeObjects.length; i++) { > rangeObjects[i] = new RangeObject(UnitLookup.NUMBER_UNITY.quantity(min), > UnitLookup.NUMBER_UNITY.quantity(max)); > min++; > max++; > } > } > }, > STACKED { > @Override > void fill(RangeObject[] rangeObjects) { > long min = 0; > long max = 2L * rangeObjects.length; > for (int i = 0; i < rangeObjects.length; i++) { > rangeObjects[i] = new RangeObject(UnitLookup.NUMBER_UNITY.quantity(min), > UnitLookup.NUMBER_UNITY.quantity(max)); > min++; > max--; > } > } > }, > SHALLOW_STACKS { > @Override > void fill(RangeObject[] rangeObjects) { > int stackDepth = 5; > long min = 0; > long max = 2 * stackDepth; > for (int i = 0; i < rangeObjects.length; i++) { > rangeObjects[i] = new RangeObject(UnitLookup.NUMBER_UNITY.quantity(min), > UnitLookup.NUMBER_UNITY.quantity(max)); > min++; > max--; > if (min == max) { > max += 2 * stackDepth; > } > } > } > }; > > abstract void fill(RangeObject[] rangeObjects); > } > > @Param({"ASCENDING", "DESCENDING", "SCRAMBLED", "OVERLAPS", "STACKED", "SHALLOW_STACKS"}) > Scenario scenario; > > @Param({"10000"}) > int numEvents; > private RangeObject[] input; > > @Setup(Level.Trial) > public void setup() { > input = new RangeObject[numEvents]; > scenario.fill(input); > } > > @Benchmark > public DisjointBuilder build() { > DisjointBuilder builder = new DisjointBuilder<>(START, END); > for (RangeObject rangeObject : input) { > builder.add(rangeObject); > } > return builder; > } > } > > > Good performance is maintained in the common ascending/disjoint case, but the degenerate cases perform much better: > > Before: > > Benchmark (numEvents) (scenario) Mode Cnt Score Error Units > DisjointBuilderBenchmark.build 10000 ASCENDING avgt 5 96.050 ? 1.240 us/op > DisjointBuilderBenchmark.build 10000 DESCENDING avgt 5 300246.685 ? 2101.505 us/op > DisjointBuilderBenchmark.build 10000 SCRAMBLED avgt 5 3977.733 ? 29.612 us/op > DisjointBuilderBenchmark.build 10000 OVERLAPS avgt 5 187.701 ? 6.161 us/op > DisjointBuilderBenchmark.build 10000 STACKED avgt 5 268306.481 ? 980.223 us/op > DisjointBuilderBenchmark.build 10000 SHALLOW_STACKS avgt 5 414.298 ? 5.719 us/op > > After: > > Benchmark (numEvents) (scenario) Mode Cnt Score Error Units > DisjointBuilderBenchmark.build 10000 ASCENDING avgt 5 91.583 ? 1.070 us/op > DisjointBuilderBenchmark.build 10000 DESCENDING avgt 5 608.281 ? 9.338 us/op > DisjointBuilderBenchmark.build 10000 SCRAMBLED avgt 5 596.601 ? 18.243 us/op > DisjointBuilderBenchmark.build 10000 OVERLAPS avgt 5 181.349 ? 1.012 us/op > DisjointBuilderBenchmark.build 10000 STACKED avgt 5 555.167 ? 13.316 us/op > DisjointBuilderBenchmark.build 10000 SHALLOW_STACKS avgt 5 353.700 ? 9.387 us/op This pull request has now been integrated. Changeset: 5c497ba1 Author: Richard Startin Committer: Henrik Dafg?rd URL: https://git.openjdk.org/jmc/commit/5c497ba19b3359ef72d0c4f3c228f0fe3383e58f Stats: 64 lines in 1 file changed: 40 ins; 8 del; 16 mod 7950: Better DisjointBuilder performance for events not ordered by event end attribute Reviewed-by: jbachorik, hdafgard ------------- PR: https://git.openjdk.org/jmc/pull/449 From hdafgard at openjdk.org Sat Nov 19 21:34:14 2022 From: hdafgard at openjdk.org (Henrik =?UTF-8?B?RGFmZ8OlcmQ=?=) Date: Sat, 19 Nov 2022 21:34:14 GMT Subject: RFR: 7978: Add new metric prefixes Message-ID: This PR adds the new metric prefixes quecto, ronto, ronna & quetta. ------------- Commit messages: - Add support for new metric prefixes Changes: https://git.openjdk.org/jmc/pull/454/files Webrev: https://webrevs.openjdk.org/?repo=jmc&pr=454&range=00 Issue: https://bugs.openjdk.org/browse/JMC-7978 Stats: 56 lines in 5 files changed: 44 ins; 0 del; 12 mod Patch: https://git.openjdk.org/jmc/pull/454.diff Fetch: git fetch https://git.openjdk.org/jmc pull/454/head:pull/454 PR: https://git.openjdk.org/jmc/pull/454 From hirt at openjdk.org Sat Nov 19 21:59:43 2022 From: hirt at openjdk.org (Marcus Hirt) Date: Sat, 19 Nov 2022 21:59:43 GMT Subject: RFR: 7978: Add new metric prefixes In-Reply-To: References: Message-ID: On Sat, 19 Nov 2022 21:28:44 GMT, Henrik Dafg?rd wrote: > This PR adds the new metric prefixes quecto, ronto, ronna & quetta. The fact that Jupiter is around 2 quettagrams is fun. That said, I believe it'll be some time before these prefixes have practical use in our particular context. ;) ------------- Marked as reviewed by hirt (Lead). PR: https://git.openjdk.org/jmc/pull/454 From hdafgard at openjdk.org Sat Nov 19 22:21:19 2022 From: hdafgard at openjdk.org (Henrik =?UTF-8?B?RGFmZ8OlcmQ=?=) Date: Sat, 19 Nov 2022 22:21:19 GMT Subject: RFR: 7978: Add new metric prefixes In-Reply-To: References: Message-ID: On Sat, 19 Nov 2022 21:56:25 GMT, Marcus Hirt wrote: > The fact that Jupiter is around 2 quettagrams is fun. That said, I believe it'll be some time before these prefixes have practical use in our particular context. ;) Probably. But good to be prepared! ;) ------------- PR: https://git.openjdk.org/jmc/pull/454 From hdafgard at openjdk.org Sun Nov 20 13:40:19 2022 From: hdafgard at openjdk.org (Henrik =?UTF-8?B?RGFmZ8OlcmQ=?=) Date: Sun, 20 Nov 2022 13:40:19 GMT Subject: Integrated: 7978: Add new metric prefixes In-Reply-To: References: Message-ID: On Sat, 19 Nov 2022 21:28:44 GMT, Henrik Dafg?rd wrote: > This PR adds the new metric prefixes quecto, ronto, ronna & quetta. This pull request has now been integrated. Changeset: c34d1ad4 Author: Henrik Dafg?rd URL: https://git.openjdk.org/jmc/commit/c34d1ad4318d287ec2f542d68789a260fdcfcbec Stats: 56 lines in 5 files changed: 44 ins; 0 del; 12 mod 7978: Add new metric prefixes Reviewed-by: hirt ------------- PR: https://git.openjdk.org/jmc/pull/454 From duke at openjdk.org Mon Nov 21 09:53:03 2022 From: duke at openjdk.org (Richard Startin) Date: Mon, 21 Nov 2022 09:53:03 GMT Subject: RFR: 7979: Reduce allocation rate in ParserStats Message-ID: Somewhat surprisingly, the capturing lambdas and the `Long`s being updated here are one of the highest allocation sources when using jmc-common as a backend library, this PR has reduced our allocation rate by about 5%. ------------- Commit messages: - 7979: Reduce allocation rate in ParserStats Changes: https://git.openjdk.org/jmc/pull/455/files Webrev: https://webrevs.openjdk.org/?repo=jmc&pr=455&range=00 Issue: https://bugs.openjdk.org/browse/JMC-7979 Stats: 34 lines in 1 file changed: 5 ins; 13 del; 16 mod Patch: https://git.openjdk.org/jmc/pull/455.diff Fetch: git fetch https://git.openjdk.org/jmc pull/455/head:pull/455 PR: https://git.openjdk.org/jmc/pull/455 From jpbempel at openjdk.org Wed Nov 23 19:16:33 2022 From: jpbempel at openjdk.org (Jean-Philippe Bempel) Date: Wed, 23 Nov 2022 19:16:33 GMT Subject: RFR: 7979: Reduce allocation rate in ParserStats In-Reply-To: References: Message-ID: On Mon, 21 Nov 2022 09:45:32 GMT, Richard Startin wrote: > Somewhat surprisingly, the capturing lambdas and the `Long`s being updated here are one of the highest allocation sources when using jmc-common as a backend library, this PR has reduced our allocation rate by about 5%. Thanks, LGTM As we are in 9 branch, could we consider including a lib like fastutil for dealing better with primitives collections? ------------- Marked as reviewed by jpbempel (Committer). PR: https://git.openjdk.org/jmc/pull/455 From egahlin at openjdk.org Wed Nov 23 19:35:25 2022 From: egahlin at openjdk.org (Erik Gahlin) Date: Wed, 23 Nov 2022 19:35:25 GMT Subject: RFR: 7979: Reduce allocation rate in ParserStats In-Reply-To: References: Message-ID: On Wed, 23 Nov 2022 19:12:48 GMT, Jean-Philippe Bempel wrote: > As we are in 9 branch, could we consider including a lib like fastutil for dealing better with primitives collections? Long time ago, when most people had 32-bit OS, I experimented with storing JMC values in primitive arrays, mostly to reduce memory. Problem was when values needed to be visualized in a table. You either had to implement sorting, filtering, formatting etc. for every type or convert it to Object/Comparable. If you converted it to an object, the GUI became sluggish when processing values in the table. Today there are better garbage collectors etc. but it may be interesting to know. ------------- PR: https://git.openjdk.org/jmc/pull/455 From duke at openjdk.org Wed Nov 23 19:41:55 2022 From: duke at openjdk.org (Richard Startin) Date: Wed, 23 Nov 2022 19:41:55 GMT Subject: RFR: 7979: Reduce allocation rate in ParserStats In-Reply-To: References: Message-ID: On Wed, 23 Nov 2022 19:12:48 GMT, Jean-Philippe Bempel wrote: > Thanks, LGTM > > As we are in 9 branch, could we consider including a lib like fastutil for dealing better with primitives collections? I'm not sure that would help here, as concurrency support is required, but it would help if the fallback in `FastAccessNumberMap` could be swapped out for something that doesn't box the constant identifiers (or if there were just no fallback at all and the paginated array could just grow indefinitely) ------------- PR: https://git.openjdk.org/jmc/pull/455 From jpbempel at openjdk.org Wed Nov 23 20:43:59 2022 From: jpbempel at openjdk.org (Jean-Philippe Bempel) Date: Wed, 23 Nov 2022 20:43:59 GMT Subject: RFR: 7979: Reduce allocation rate in ParserStats In-Reply-To: References: Message-ID: On Wed, 23 Nov 2022 19:38:48 GMT, Richard Startin wrote: > > I'm not sure that would help here, as concurrency support is required, yeah agree on this case. > but it would help if the fallback in `FastAccessNumberMap` could be swapped out for something that doesn't box the constant identifiers (or if there were just no fallback at all and the paginated array could just grow indefinitely) I have tested on this particular Map to use fastutil and numbers were significantly better, but it was not the time to integrate a new dependency, that's why I am throwing again the idea ------------- PR: https://git.openjdk.org/jmc/pull/455 From jpbempel at openjdk.org Wed Nov 23 20:44:00 2022 From: jpbempel at openjdk.org (Jean-Philippe Bempel) Date: Wed, 23 Nov 2022 20:44:00 GMT Subject: RFR: 7979: Reduce allocation rate in ParserStats In-Reply-To: References: Message-ID: On Wed, 23 Nov 2022 19:31:59 GMT, Erik Gahlin wrote: > > As we are in 9 branch, could we consider including a lib like fastutil for dealing better with primitives collections? > > Long time ago, when most people had 32-bit OS, I experimented with storing JMC values in primitive arrays, mostly to reduce memory. Problem was when values needed to be visualized in a table. You either had to implement sorting, filtering, formatting etc. for every type or convert it to Object/Comparable. If you converted it to an object, the GUI became sluggish when processing values in the table. Today there are better garbage collectors etc. but it may be interesting to know. Thanks for the input! ------------- PR: https://git.openjdk.org/jmc/pull/455 From duke at openjdk.org Wed Nov 23 21:08:25 2022 From: duke at openjdk.org (Richard Startin) Date: Wed, 23 Nov 2022 21:08:25 GMT Subject: Integrated: 7979: Reduce allocation rate in ParserStats In-Reply-To: References: Message-ID: On Mon, 21 Nov 2022 09:45:32 GMT, Richard Startin wrote: > Somewhat surprisingly, the capturing lambdas and the `Long`s being updated here are one of the highest allocation sources when using jmc-common as a backend library, this PR has reduced our allocation rate by about 5%. This pull request has now been integrated. Changeset: 68387c5b Author: Richard Startin Committer: Jean-Philippe Bempel URL: https://git.openjdk.org/jmc/commit/68387c5bd454fcf4bdda07d0cbe8d6eb59e2a840 Stats: 34 lines in 1 file changed: 5 ins; 13 del; 16 mod 7979: Reduce allocation rate in ParserStats Reviewed-by: jpbempel ------------- PR: https://git.openjdk.org/jmc/pull/455