-
Notifications
You must be signed in to change notification settings - Fork 5.7k
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
8282024: add EscapeAnalysis statistics under PrintOptoStatistics #8019
Conversation
👋 Welcome back aamarsh! A progress list of the required criteria for merging this PR into |
Webrevs
|
hi, @aamarsh , In your case, NoEscape/Objects scalar replaced is 124/172. One potential explanation is that you encounter many boxing objects. Is this case?
I see that you add static counters to ConnectionGraph and PhaseMacroExpand. Do we need to use Atomic::add in case many C2 compiler threads run in parallel. if you combine CICompilerCount and -Xcomp, can you see those counters are stable values? Even we won't completely mess up counters, it may lose values in multi-threaded environment.
|
be8e235
to
2b7edc4
Compare
hi, @navyxliu Yes, you are correct that scalar replaced objects should be a subset of NonEscape objects. In my implementation I was resetting the NonEscape counter if escape analysis was called multiple times on a ConnectionGraph. Unfortunately I was forgetting to count the objects that had been scalar replaced in between escape analysis calls. I have updated my logic to support this and I updated the provided example. Thank you for catching that! As for using static counters, the thought of a multi-threaded environment did come up. I looked at other static counters printed in |
hi, @aamarsh , |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hi,
Thank you for working on this. In generally, I think it looks good. only small suggests left.
It seems that you use git reset and push it forcely. That's why you only have one commit displayed in this PR. I think it's easier for people to keep track your changes incrementally. It's totally okay you keep committing to your branch. github will squash them when it merges a PR. please refrain from push by force. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LTGM. I am not a reviewer. We need other reviewers to approve it.
src/hotspot/share/opto/escape.cpp
Outdated
else if (ptn->escape_state() == PointsToNode::ArgEscape) { | ||
_compile->_local_arg_escape_ctr++; | ||
} | ||
else if (ptn->escape_state() == PointsToNode::GlobalEscape) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"else if" style is not consistent with others.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIT: Move "else if" to line 3793.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have few comments.
src/hotspot/share/opto/escape.cpp
Outdated
#ifndef PRODUCT | ||
escape_state_statistics(java_objects_worklist); | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use NOT_PRODUCT()
macro for one line which you have a lot in these changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIT: Use NOT_PRODUCT
src/hotspot/share/opto/escape.cpp
Outdated
_compile->_local_no_escape_ctr = 0; | ||
_compile->_local_arg_escape_ctr = 0; | ||
_compile->_local_global_escape_ctr = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think you need these Compile
counters - make them local to update corresponding ConnectionGraph
counters after loop. As I said these counters are not accurate anyway. Unless you want to track for which allocation which counter was recorded. Which I think will be over-kill because the most EA done with one iteration.
src/hotspot/share/opto/macro.hpp
Outdated
static int _monitor_objects_removed_counter; | ||
static int _GC_barriers_removed_counter; | ||
static int _memory_barriers_removed_counter; | ||
int _local_scalar_replaced; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't need _local_scalar_replaced
value as I said in an other comment.
src/hotspot/share/opto/escape.cpp
Outdated
void ConnectionGraph::print_statistics() { | ||
tty->print("No escape = %d, Arg escape = %d, Global escape = %d", Atomic::load(&_no_escape_counter), Atomic::load(&_arg_escape_counter), Atomic::load(&_global_escape_counter)); | ||
tty->print(" (EA executed in %7.2f seconds)", Atomic::load(&_time_elapsed) * 0.001); | ||
tty->print_cr(" ** EA stats might be slightly off since objects might be double counted due to iterative EA **"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need to print this warning. I suggest to put it as comment in this method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for addressing my comment. I have only one left.
I started testing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
About time statistic. There is flag -XX:+CITime which prints times for all phases in C2 (and C1). For EA it is _t_escapeAnalysis
. And I see difference in reported times (0.02 vs 0.059).
Your output:
(EA executed in 0.02 seconds)
CITime:
Escape Analysis: 0.076 s
Conn Graph: 0.059 s
Macro Eliminate: 0.027 s
I simply run fastdebug VM with -Xcomp:
java -XX:+PrintOptoStatistics -XX:+CITime -Xcomp t
It is up to you but I would suggest to remove your change to collect time since we have it already with CITime. |
src/hotspot/share/opto/escape.cpp
Outdated
@@ -3739,6 +3752,31 @@ void ConnectionGraph::dump(GrowableArray<PointsToNode*>& ptnodes_worklist) { | |||
} | |||
} | |||
|
|||
void ConnectionGraph::print_statistics() { | |||
// EA stats might be slightly off since objects might be double counted due to iterative EA |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand. your approach almost worked in last revision. All you need to do is to adjust for the last iteration.
This revision drops it. I don't think it would be "slightly" off, even double counted is optimistic. A java object will be counted repeat if iterEA iterates N times. My concern is the final statistical counters become incomparable.
Why did you drop snapshot approach in 0805514?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@navyxliu, please, explain what do you mean "snapshot approach" and suggest how we should do it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In previous revision, @aamarsh used 3 data members of Compile. This tuple is a snapshot.
_local_no_escape_ctr
_local_arg_escape_ctr
_local_global_escape_ctr
ConnectionGraph::escape_state_statistics() initializes them all zeros and categorize Java objects of the connection graph.
here is the framework.
do {
EscapeAnalysis();
MacroExpand.eliminate_macro_nodes();
} while (progress?);
#ifndef PRODUCT
Atomic::add(&ConnectionGraph::_no_escape_counter, _local_no_escape_ctr + total_scalar_replaced);
Atomic::add(&ConnectionGraph::_arg_escape_counter, _local_arg_escape_ctr);
Atomic::add(&ConnectionGraph::_global_escape_counter, _local_global_escape_ctr);
#endif
Both you and @JohnTortugo pointed out that there was a bug in previous revision. We overlook that non-escaped objects are double-counted in last iteration. I think it's amendable.
I call this snapshot approach because it uses the snapshot of last iteration to update global statistical counters. all intermediate snapshots are drop. Allow me to write down @aamarsh 's approach.
The number of Java object JO
is from user-program by nature. EscapeAnalysis breaks them down into 3 categories. non-escaped, arg-escaped and global escaped. Without iterative EA, we can report this snapshot to statistical counters.
With iterative EA, a problem arise. Some objects elided in previous iteration of MacroExpansion. if we use last snapshot, we have to add those eliminated java objects. Let's say iterative EA iterates N times in total. E
is the number of eliminated java object from 1 to N-1 iterations (exclude the last iteration here).
Since all eliminated objects must be non-escaped, so we add E back to _no_escape_counter. We account for all java objects of this compilation unit.
Atomic::add(&ConnectionGraph::_no_escape_counter, _local_no_escape_ctr + E);
Atomic::add(&ConnectionGraph::_arg_escape_counter, _local_arg_escape_ctr);
Atomic::add(&ConnectionGraph::_global_escape_counter, _local_global_escape_ctr);
In this way, We keep track of all java objects of this CU for iterative EA. I think it's accurate.
JO = _local_no_escape_ctr + E + _local_arg_escape_ctr + _local_global_escape_ctr
I suggest to hoist the variable PhaseMacroExpand mexp
out of loop and make it stateful to track E.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it. Thank for explaining - you simply used data from last iteration.
I think you can do similar with much less complexity if you used data from first iteration and current code change:
void ConnectionGraph::escape_state_statistics(GrowableArray<JavaObjectNode*>& java_objects_worklist) {
if (!PrintOptoStatistics || (_invocation > 0)) { // Collect data only for first invocation
return;
}
for (int next = 0; next < java_objects_worklist.length(); ++next) {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to revert escape_state_statistics
back to non static for this of cause.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so you use the snapshot of first iteration. We assume Iterative EA can elide some non-escaped objects but can't change any object's category. I think it is correct and indeed much simpler!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That was a great idea. Thank you all. I'll work with @aamarsh to do the changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. I am not a reviewer. we need other reviewers to approve this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. I verified output.
@aamarsh 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:
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 818 new commits pushed to the
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. As you do not have Committer status in this project an existing Committer must agree to sponsor your change. Possible candidates are the reviewers of this PR (@navyxliu, @vnkozlov) but any other Committer may sponsor as well. ➡️ To flag this PR as ready for integration with the above commit message, type |
@vnkozlov It looks like there are two Windows x64 tests failing and after a re-run they have been stuck on the task for 20 hours. The failure happened at: tools/javac/Paths/MineField.sh with the message:
It does not appear that my code would effect these tests, but I don't want to integrate if the check are are not all passing. |
@aamarsh Do not worry. I see other latest PRs has the same failure. Your changes should not affect product version of JDK. |
/integrate |
Hi, can someone please sponsor this PR if all looks good? TIA! |
Give me time to quick test to make sure it builds on all our systems. I will sponsor after that. |
No worries. Thank you Vladimir! |
/sponsor |
Going to push as commit 2f19144.
Your commit was automatically rebased without conflicts. |
Escape Analysis and Scalar Replacement statistics were added when the -XX:+PrintOptoStatistics flag is set. All code is placed in
#ifndef Product
block, so this code is only run when creating a debug build. Using renaissance benchmark I ran a few tests to confirm that numbers were printing correctly. Below is an example run:Progress
Issue
Reviewers
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.java.net/jdk pull/8019/head:pull/8019
$ git checkout pull/8019
Update a local copy of the PR:
$ git checkout pull/8019
$ git pull https://git.openjdk.java.net/jdk pull/8019/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 8019
View PR using the GUI difftool:
$ git pr show -t 8019
Using diff file
Download this PR as a diff file:
https://git.openjdk.java.net/jdk/pull/8019.diff