Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8261847: performance of java.lang.Record::toString should be improved #6403

Closed

Conversation

vicente-romero-oracle
Copy link
Contributor

@vicente-romero-oracle vicente-romero-oracle commented Nov 16, 2021

Please review this PR which aims to optimize the implementation of the toString method we provide for records. A benchmark comparing the implementation we are providing for records with lombok found out that lombok is much faster mainly because our implementation uses String::format. This fix is basically delegating on StringConcatFactory::makeConcatWithConstants which is faster.

TIA

This is the result of the benchmark comparing records to lombok with vanilla JDK:

Benchmark                          Mode  Cnt    Score    Error  Units
MyBenchmark.base                   avgt    4    0.849 ±  0.111  ns/op
MyBenchmark.equals_record          avgt    4    7.343 ±  2.740  ns/op
MyBenchmark.equals_value           avgt    4    6.644 ±  1.920  ns/op
MyBenchmark.record_hash_code       avgt    4    5.763 ±  3.882  ns/op
MyBenchmark.record_to_string       avgt    4  262.626 ± 12.574  ns/op               <------ Before
MyBenchmark.value_class_to_string  avgt    4   30.325 ± 21.389  ns/op
MyBenchmark.value_hash_code        avgt    4    5.048 ±  3.936  ns/op

after this patch:

Benchmark                          Mode  Cnt   Score   Error  Units
MyBenchmark.base                   avgt    4   0.680 ± 0.185  ns/op
MyBenchmark.equals_record          avgt    4   5.599 ± 1.348  ns/op
MyBenchmark.equals_value           avgt    4   5.718 ± 4.633  ns/op
MyBenchmark.record_hash_code       avgt    4   4.628 ± 4.368  ns/op
MyBenchmark.record_to_string       avgt    4  26.791 ± 1.817  ns/op                 <------- After
MyBenchmark.value_class_to_string  avgt    4  35.473 ± 2.626  ns/op
MyBenchmark.value_hash_code        avgt    4   6.152 ± 5.101  ns/op

Progress

  • Change must not contain extraneous whitespace
  • Commit message must refer to an issue
  • Change must be properly reviewed

Issue

  • JDK-8261847: performance of java.lang.Record::toString should be improved

Reviewers

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.java.net/jdk pull/6403/head:pull/6403
$ git checkout pull/6403

Update a local copy of the PR:
$ git checkout pull/6403
$ git pull https://git.openjdk.java.net/jdk pull/6403/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 6403

View PR using the GUI difftool:
$ git pr show -t 6403

Using diff file

Download this PR as a diff file:
https://git.openjdk.java.net/jdk/pull/6403.diff

@bridgekeeper
Copy link

bridgekeeper bot commented Nov 16, 2021

👋 Welcome back vromero! A progress list of the required criteria for merging this PR into master will be added to the body of your pull request. There are additional pull request commands available for use with this pull request.

@openjdk openjdk bot added the rfr Pull request is ready for review label Nov 16, 2021
@openjdk
Copy link

openjdk bot commented Nov 16, 2021

@vicente-romero-oracle The following label will be automatically applied to this pull request:

  • core-libs

When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing list. If you would like to change these labels, use the /label pull request command.

@openjdk openjdk bot added the core-libs core-libs-dev@openjdk.org label Nov 16, 2021
@mlbridge
Copy link

mlbridge bot commented Nov 16, 2021

Webrevs

@shipilev
Copy link
Member

There is a limit on the number of arguments that you can feed into SCF, what happens if we reach it? E.g. what if we have the Record with too many components?

Class<?>[] types = Stream.of(getters)
.map(g -> g.type().returnType())
.toList()
.toArray(new Class<?>[getters.length]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not new Class[0]? It's likely to be faster, isn't it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I'm not reviewer.)

I think .toArray(Class<?>[]::new) should be better here. .toList seems unnecessary.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

   Class<?>[] types = Stream.of(getters)
            .map(g -> g.type().returnType())
            .toArray(Class<?>[]::new);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or do not use a stream but a simple loop, codes in bootstrap methods should be low-level

@JimLaskey
Copy link
Member

As Aleksey mentioned, you need a fallback for more that 200 components (limit of StringConcatFactory).

@liach
Copy link
Member

liach commented Nov 16, 2021

I recall string concat indy supports up to 200 args while a record can have max 254 components. should we add a test case with a 254-component record to ensure its toString will execute without exceptions?

@cl4es
Copy link
Member

cl4es commented Nov 16, 2021

More specifically the StringConcatFactory limit is 200 argument slots, not arguments.

Tests exercising maxed out records sounds like something we need to add if such doesn't already exist somewhere.

@vicente-romero-oracle
Copy link
Contributor Author

thanks all for the comments! I will be uploading a new iteration soon

@JarvisCraft
Copy link
Contributor

By the way, considering the fact that the limit of StringConcatFactory (i.e. 200 arguments) is explicitly specified (at least, it is mentioned in its Javadoc) can we request to have it available to code (e.g. as a public static final constant) so that other code in JDK (like this PR) and foreign code can rely on it?

For example, I have to duplicate this value based on Javadoc here while there could have been something similar to StringConcatFactory#MAX_ARGUMENTS.

@vicente-romero-oracle
Copy link
Contributor Author

vicente-romero-oracle commented Nov 17, 2021

I have uploaded another iteration, this one can deal with any number of record components, some numbers for when the number of record components is pushed to the maximum (254 components):

JDK18 vanilla:

Benchmark                          Mode  Cnt      Score      Error  Units
MyBenchmark.base                   avgt    4      0.670 ±    0.078  ns/op
MyBenchmark.equals_record          avgt    4   9092.649 ±  400.200  ns/op
MyBenchmark.equals_value           avgt    4    107.184 ±   15.993  ns/op
MyBenchmark.record_hash_code       avgt    4   6284.711 ± 1985.212  ns/op
MyBenchmark.record_to_string       avgt    4  69614.364 ± 6310.593  ns/op
MyBenchmark.value_class_to_string  avgt    4  25910.041 ± 7822.274  ns/op
MyBenchmark.value_hash_code        avgt    4    315.969 ±   36.545  ns/op

With this PR:

Benchmark                          Mode  Cnt      Score      Error  Units
MyBenchmark.base                   avgt    4      0.658 ±    0.053  ns/op
MyBenchmark.equals_record          avgt    4   8222.407 ±  308.440  ns/op
MyBenchmark.equals_value           avgt    4    102.627 ±   56.522  ns/op
MyBenchmark.record_hash_code       avgt    4   6030.478 ±  243.390  ns/op
MyBenchmark.record_to_string       avgt    4  46504.151 ± 3597.182  ns/op
MyBenchmark.value_class_to_string  avgt    4  26196.565 ± 8154.037  ns/op
MyBenchmark.value_hash_code        avgt    4    313.918 ±    4.577  ns/op

some observations, we are doing better than before but still worst than lombok. I don't think having to create a more complicated MH tree is the key, our numbers are still worst even if there is no need to create too much levels in the MH tree like for 100 record components occupying a spot each. Another observation is that even though our slowest implementation is the one for the toString method, in absolute terms, lombok is faster in all cases. So more work could be necessary for the rest of the methods if deemed worthy.

Thanks!

@vicente-romero-oracle
Copy link
Contributor Author

vicente-romero-oracle commented Nov 19, 2021

I have done some additional experiments as suggested by Claes, thanks, for different number of record components. In all cases all the components are of type int so they occupy only one slot. Here are some numbers. I tried with 0, 1, 10, 100 and 254 record components.

Benchmark                                  Mode  Cnt      Score       Error  Units
MyBenchmark.base                           avgt    4      0.775 ±     0.552  ns/op
MyBenchmark.record0_toString               avgt    4      4.973 ±     2.800  ns/op
MyBenchmark.record1_toString               avgt    4     16.026 ±     5.100  ns/op
MyBenchmark.record10_toString              avgt    4     81.412 ±     3.365  ns/op
MyBenchmark.record100_toString             avgt    4  12269.500 ±   179.784  ns/op
MyBenchmark.record254_toString             avgt    4  51191.953 ± 11679.762  ns/op
MyBenchmark.valueClass0_toString           avgt    4      5.134 ±     2.372  ns/op
MyBenchmark.valueClass1_toString           avgt    4     23.321 ±     9.234  ns/op
MyBenchmark.valueClass10_toString          avgt    4     94.048 ±     7.017  ns/op
MyBenchmark.valueClass100_toString         avgt    4   9253.282 ±  4843.738  ns/op
MyBenchmark.valueClass254_toString         avgt    4  31963.158 ± 24050.499  ns/op

Then also after a suggestion from Claes I modified the maximum number of slots I would be chopping the arguments into, I gave a try with 20 slots and got these numbers:

Benchmark                                  Mode  Cnt      Score       Error  Units
MyBenchmark.record0_toString               avgt    4      5.009 ±     3.454  ns/op
MyBenchmark.record1_toString               avgt    4     14.207 ±    10.551  ns/op
MyBenchmark.record10_toString              avgt    4     81.018 ±     7.320  ns/op
MyBenchmark.record100_toString             avgt    4   2862.641 ±  1233.862  ns/op
MyBenchmark.record254_toString             avgt    4  23002.280 ± 97103.923  ns/op
MyBenchmark.valueClass0_toString           avgt    4      4.967 ±     3.947  ns/op
MyBenchmark.valueClass1_toString           avgt    4     23.756 ±     8.499  ns/op
MyBenchmark.valueClass10_toString          avgt    4     87.691 ±     7.956  ns/op
MyBenchmark.valueClass100_toString         avgt    4   9539.272 ±  9461.516  ns/op
MyBenchmark.valueClass254_toString         avgt    4  28323.478 ± 11932.474  ns/op

It seems like the execution is way faster for these number of slots.

@lgxbslgx
Copy link
Member

FYI: this patch also seems to solve JDK-8265747.

@vicente-romero-oracle
Copy link
Contributor Author

FYI: this patch also seems to solve JDK-8265747.

yep, although I prefer to keep JDK-8265747 because it is also referring to the hashCode method, and so far I have been focusing on the toString only which is the one for which we have the worst performance right now. Thanks for the heads-up

@cl4es
Copy link
Member

cl4es commented Nov 19, 2021

It seems like the execution is way faster for these number of slots.

I suggested this experiment to split up the concatenations more aggressively to diagnose if we're having an issue here where the performance of the method handle produced by StringConcatFactory degrades after some number of arguments compared to a more traditional concatenation (as exemplified by the Lombok valueClass tests). And that seems to be the case.

While I haven't analyzed the root cause here (I think it seems likely that the JIT bails out at some point when the MH combinator tree grows too large or more likely too deep (long?)) I'd characterize this is a performance bug in the StringConcatFactory. This might be straightforward to address by moving the splitting logic you do here inside StringConcatFactory. This should be done as a follow-up.

Assuming all you had to do to improve over the current patch was set your local MAX_INDY_CONCAT_ARG_SLOTS constant to 20 I think it's fine to put that in - we'll want to look at simplifying the ObjectMethods code once StringConcatFactory better deals with many arguments anyhow.

@stuart-marks
Copy link
Member

Regarding the slot limit in StringConcatFactory, it's not clear to me the limit of 200 is normative or is merely an implementation note. The limit of 200 slots seems to be arbitrary and shouldn't be baked into the spec. Perhaps this limit can be removed if the splitting logic is moved into StringConcatFactory.

@JimLaskey
Copy link
Member

I think this splitting logic only works for special cases. In this case, when there is only one object acting as the source of all values. Other splitting solutions needing more inputs require multiple method handles and multiple calls because of these complexly determined limits. The immediate solution here would be to define a static final constant like MAX–STRING-CONCAT–SLOTS and leave the number unspecified. I believe 200 was chosen because it was arbitrarily safe. As Vicente and Claes have shown and I verified in the templated string work, 20-25 slots per call seems to be the sweet spot. Having the resulting method with more inputs seems to make it more difficult to JIT optimize.

@cl4es
Copy link
Member

cl4es commented Nov 20, 2021

@stuart-marks yes, a general purpose splitting logic moved into the StringConcatFactory would be able to get rid of the arbitrary 200 slot limit (we would hit a harder but less arbitrary limit at around 253 instead).

@JimLaskey I don't see why it wouldn't work generally from the point of view of the StringConcatFactory: Vicente's code operates on a MethodHandle[] with getters as inputs to the SCF bootstrap method, whereas SCF would deal with arguments directly (retrieved from an Object[]). I think the code changes from the patch here after moving the logic into SCF should be pretty minimal and straightforward: if I'm not missing anything we'd only conceptually be replacing the filterArguments on line 313 with an insertArguments.

@JarvisCraft
Copy link
Contributor

JarvisCraft commented Nov 20, 2021

Regarding the slot limit in StringConcatFactory, it's not clear to me the limit of 200 is normative or is merely an implementation note. The limit of 200 slots seems to be arbitrary and shouldn't be baked into the spec. Perhaps this limit can be removed if the splitting logic is moved into StringConcatFactory.

Too me it looks as if it something that has to be considered as part of the specification, at least in the current state.
The Javadoc explicitly states that:

<...> the following linkage invariants must hold:

  • The number of parameter slots in concatType is less than or equal to 200
    <...>
    Throws:
    StringConcatException - If any of the linkage invariants described here are violated, or the lookup context does not have private access privileges.

If it was an unspecified implementation detail, than arbitrary compilers (at least if we speak about javac) would have no formal reason to stick to this limit instead of using max available number of slots, which currently would lead to runtime StringConcatException.

For this reason the current state (IMO) should be considered the part of the specification and thus it seems reasonable to either:

  • make it available to other code (via a public constant, at least)
  • remove the magical number limit (as suggested by @stuart-marks and @cl4es) so that compilers no longer have to depend on a semi-specified magical number
  • add an analog of current StringConcatFactory to some other place (java.lang.runtime seems to be a nice place, considering how most new invokedynamic-related bootstraps live there) but make it more strictly specified and keep the current StringConcatFactory untouched (simply delegating to the new one)

I understand that this is mostly out of this PR's scope and should definitely be discussed more wisely but I guess that it's worth starting this discussion here where it can be seen as an issue.

@JimLaskey
Copy link
Member

@cl4es I was thinking of the more general case 200 < N. You were in the 200 < N < 253 case. I think it would be better to pass in a chunk size (<= 200) and an array of ptype and get an array of method handles each taking a chunk size of arguments plus result of prior call. This is more like what javac does.

@vicente-romero-oracle
Copy link
Contributor Author

vicente-romero-oracle commented Nov 21, 2021

Thanks guys for the discussion so far. I wanted to add some graphs I generated. I modified the code at ObjectMethods to split the getters in slot sizes from 10 to 200 in increments of 10. Then I executed the benchmark with the given slot size for records and lombok classes with int and String components. In every case the record and the lombok class had all ints or all String components / fields. I collected data for 1, 10, 100 and 254 components / fields. See below the graphical representation of the data I got. Some comments below analyzing the data for records:

1 component

As expected the slot size doesn't matter much for this case as we are dealing with only one component:
1Component

10 components

Here the slot size doesn't make a big difference as expected. There is a tight range for the case when all the components are ints. For the string case the range is also very tight modulo a couple of data points but we could safely say that the numbers are pretty good for slots sizes from 10-80:
10Components

100 components

Here we start seeing the number of slots playing a more important role. See how the time grows in a quasi logarithmic function for 100 string components once the slot size is greater than 70, for the all integers case we get pretty good numbers up to slot size 60:
100Components

254 components

The results for 254 integer components show a lot of variation. The results are good for slot sizes 10, 20 and then for most sizes from 70 to 170, not for 150. Whereas for the all strings case we have good numbers up to slot size 60 and it picks up from there:
254Components

So these data seems to confirm that slot sizes from 10-30 is where we want to be. I will update the patch to use 20 slots to split the getters. Thanks again for the discussion!

@vicente-romero-oracle
Copy link
Contributor Author

hi guys, can I have a thumbs up for this one? I will continue doing additional research for the hashCode and equals methods as a follow up but would like to close this one as the performance for the Record::toString was the worst compared to lombok.

TIA

constants[1 + 2 * i] = names.get(i) + "=";
if (i != names.size() - 1) {
constants[1 + 2 * i + 1] = ", ";
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wondering if it would be cleaner to use a full recipe.

        StringBuilder recipeSB = new StringBuilder();
        recipeSB.append(receiverClass.getSimpleName());
        recipeSB.append('[');

        for (int i = 0; i < names.size(); i++) {
            if (i != 0) {
                recipeSB.append(", ");
            }

            recipeSB.append(names.get(i));
            recipeSB.append('=');
            recipeSB.append('\1');
        }

        recipeSB.append(']');
        String recipe = recipeSB.toString();

@cl4es
Copy link
Member

cl4es commented Nov 22, 2021

FWIW I did a few experiments trying to move the chunking to SCF. Most made things worse, but this is getting close: https://github.com/openjdk/jdk/compare/master...cl4es:scf_split?expand=1

The threshold for when the JIT fails to optimize seem to be pushed up a bit and I get a 4x gains when concatenating 100 Strings (though it takes a good while for the microbenchmark to stabilize). It also fails to make much of a difference when looking at 200 arguments (maybe 1.4x win). The experiment I have done so far are crude and aggregates the results into a String builder with no size estimation, so it adds a but of unnecessary allocation that could be improved. I think this needs way more work to be a good enhancement and that splitting up outside is going to remain better for now.

A "hidden" drawback with chunking is that you're likely going to be allocating more.

I also re-realized that it'll be pretty hard (or impossible) to get around having some MH slot limit: even though we chunk it up internally, the MH we return must have a type that matches the type given to the bootstrap method, and any operations on the tree that require some temporary arguments we need to pass around will require some argument slots. The current strategy doesn't use too many temporaries, so the real limit might be around 250, but it makes sense to give some room for alternative implementations that use more temporaries if that makes things more efficient.

MethodHandle[] toSplit = getters;
int namesIndex = 0;
do {
/* StringConcatFactory::makeConcatWithConstants can only deal with 200 spots, longs and double occupy two
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typos: spot -> slot, chunck -> chunk, diference -> difference

}

/**
* Chops the getters into smaller chunks according to the maximum number of spots
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: spots -> slots

* Chops the getters into smaller chunks according to the maximum number of spots
* StringConcatFactory::makeConcatWithConstants can chew
* @param getters the current getters
* @return chunks that wont surpass the maximum number of spots StringConcatFactory::makeConcatWithConstants can chew
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

new Object[0]
).getTarget();
mhs[splitIndex] = MethodHandles.filterArguments(mhs[splitIndex], 0, currentSplitGetters);
mhs[splitIndex] = MethodHandles.permuteArguments(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is some gnarly logic. Could we add some comments on what permuteArguments with a reorder array of just zeros is doing here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not unusual. It spreads a single argument across several "getters". But a comment wouldn't hurt.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't seen it used like this before. The duplication behavior is mentioned explicitly with an example in the javadoc, sure, but it still took me a deep reading of the docs to understand what was going on here and what the intent was.

@vicente-romero-oracle
Copy link
Contributor Author

@JimLaskey I'm generating several recipes one per each invocation of StringConcatFactory::makeConcatWithConstants I think that generating only one recipe is possible only if the number of getters we are dealing with is less than the maximum number of slots we want to split the getters into

@vicente-romero-oracle
Copy link
Contributor Author

FWIW I did a few experiments trying to move the chunking to SCF. Most made things worse, but this is getting close: https://github.com/openjdk/jdk/compare/master...cl4es:scf_split?expand=1

The threshold for when the JIT fails to optimize seem to be pushed up a bit and I get a 4x gains when concatenating 100 Strings (though it takes a good while for the microbenchmark to stabilize). It also fails to make much of a difference when looking at 200 arguments (maybe 1.4x win). The experiment I have done so far are crude and aggregates the results into a String builder with no size estimation, so it adds a but of unnecessary allocation that could be improved. I think this needs way more work to be a good enhancement and that splitting up outside is going to remain better for now.

A "hidden" drawback with chunking is that you're likely going to be allocating more.

I also re-realized that it'll be pretty hard (or impossible) to get around having some MH slot limit: even though we chunk it up internally, the MH we return must have a type that matches the type given to the bootstrap method, and any operations on the tree that require some temporary arguments we need to pass around will require some argument slots. The current strategy doesn't use too many temporaries, so the real limit might be around 250, but it makes sense to give some room for alternative implementations that use more temporaries if that makes things more efficient.

Thanks for sharing this and for doing the experiment!

Copy link
Member

@cl4es cl4es left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding the comment and fixing typos.

@vicente-romero-oracle
Copy link
Contributor Author

this ship is sailing! thanks everyone for the feedback and interest!

@vicente-romero-oracle
Copy link
Contributor Author

/integrate

@openjdk
Copy link

openjdk bot commented Nov 23, 2021

@vicente-romero-oracle This pull request has not yet been marked as ready for integration.

@vicente-romero-oracle
Copy link
Contributor Author

Thanks for adding the comment and fixing typos.

sure, thanks to you

@vicente-romero-oracle vicente-romero-oracle changed the title 8261847: performace of java.lang.Record::toString should be improved 8261847: performance of java.lang.Record::toString should be improved Nov 23, 2021
@openjdk
Copy link

openjdk bot commented Nov 23, 2021

@vicente-romero-oracle This change now passes all automated pre-integration checks.

ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details.

After integration, the commit message for the final commit will be:

8261847: performance of java.lang.Record::toString should be improved

Reviewed-by: jlaskey, redestad

You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed.

At the time when this comment was updated there had been 120 new commits pushed to the master branch:

  • 64bdc84: 8277649: [BACKOUT] JDK-8277507 Add jlink.debug system property while launching jpackage tests to help diagonize recent intermittent failures
  • 5e7e2da: 8272042: java.util.ImmutableCollections$Map1 and MapN should not be @valuebased
  • f4dc03e: 8276696: ParallelObjectIterator freed at the wrong time in VM_HeapDumper
  • 90f96fb: 8277441: CompileQueue::add fails with assert(_last->next() == __null) failed: not last
  • 66eaf65: 8277413: Remove unused local variables in jdk.hotspot.agent
  • 36b887a: 8277560: Remove WorkerDataArray::_is_serial
  • 017df14: 8277556: Call ReferenceProcessorPhaseTimes::set_processing_is_mt once
  • 79350b9: 8276216: Negated character classes performance regression in Pattern
  • e3243ee: 8277087: ZipException: zip END header not found at ZipFile#Source.findEND
  • 12f08ba: 8277507: Add jlink.debug system property while launching jpackage tests to help diagonize recent intermittent failures
  • ... and 110 more: https://git.openjdk.java.net/jdk/compare/fe45835f7cebfccd4544ae19d88bdc7f07560fbe...master

As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details.

➡️ To integrate this PR with the above commit message to the master branch, type /integrate in a new comment.

@openjdk openjdk bot added the ready Pull request is ready to be integrated label Nov 23, 2021
@vicente-romero-oracle
Copy link
Contributor Author

/integrate

@openjdk
Copy link

openjdk bot commented Nov 23, 2021

Going to push as commit 7b67a49.
Since your change was applied there have been 121 commits pushed to the master branch:

  • 38802ad: 8254108: ciReplay: Support incremental inlining
  • 64bdc84: 8277649: [BACKOUT] JDK-8277507 Add jlink.debug system property while launching jpackage tests to help diagonize recent intermittent failures
  • 5e7e2da: 8272042: java.util.ImmutableCollections$Map1 and MapN should not be @valuebased
  • f4dc03e: 8276696: ParallelObjectIterator freed at the wrong time in VM_HeapDumper
  • 90f96fb: 8277441: CompileQueue::add fails with assert(_last->next() == __null) failed: not last
  • 66eaf65: 8277413: Remove unused local variables in jdk.hotspot.agent
  • 36b887a: 8277560: Remove WorkerDataArray::_is_serial
  • 017df14: 8277556: Call ReferenceProcessorPhaseTimes::set_processing_is_mt once
  • 79350b9: 8276216: Negated character classes performance regression in Pattern
  • e3243ee: 8277087: ZipException: zip END header not found at ZipFile#Source.findEND
  • ... and 111 more: https://git.openjdk.java.net/jdk/compare/fe45835f7cebfccd4544ae19d88bdc7f07560fbe...master

Your commit was automatically rebased without conflicts.

@openjdk openjdk bot closed this Nov 23, 2021
@openjdk openjdk bot added integrated Pull request has been integrated and removed ready Pull request is ready to be integrated rfr Pull request is ready for review labels Nov 23, 2021
@openjdk
Copy link

openjdk bot commented Nov 23, 2021

@vicente-romero-oracle Pushed as commit 7b67a49.

💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored.

@vicente-romero-oracle vicente-romero-oracle deleted the JDK-8261847 branch November 23, 2021 15:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core-libs core-libs-dev@openjdk.org integrated Pull request has been integrated