-
Notifications
You must be signed in to change notification settings - Fork 69
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
Extract set_collection_kind and set_gc_status #957
Conversation
I got some strange performance results for the PR, running The change in this PR should be a no-op for I have no idea why this would happen. Any idea would be helpful. |
This might be an simple but interesting example for relational debugging cc @steveblackburn |
Have you been able to reproduce it on a different microarchitecture? |
I am tracing down this bug. It turns out that the number of objects scanned in each GC for the two builds are the same, but the total bytes of the scanned objects are different. The total bytes is calculated with |
The idea that Jython might behave differently with different build names is not implausible. Jython is a python implementation, and it makes a lot of sense that it sees and uses the users' "environment", and thus would be affected by the path length of the working directory in which it is run. It's alarming that it would affect the GC to this extent, but it's not implausible IMO. |
The path length will increase object size in The following is the number of GCs and the STW time for semispace, immix, and mark sweep for different path lengths. I use folder names of length 1 to 255. The X axis is the base folder SemiSpaceImmixMark SweepI will reevaluate this PR. @steveblackburn Should I open an issue for DaCapo? |
Yes, I think we need to fix this in DaCapo |
@qinsoon If you have any info on the type that is affected that would help me a great deal. |
I will see if I can narrow it down to some types. It may not be that easy: 1. It is possible that those are some string types that have increased sizes. But what we are really interested is the types that reference the strings, which probably won't have a size difference. 2. We can only tell what types have increased size by comparing two builds. If we just look into one build, we cannot tell much. The only info that I know is probably the affected types are larger than 100 bytes. I will probably start by finding out what types have more than 100 bytes. I will see what I can find out. |
@caizixian and I looked at this together. It turned out to be an issue of me using 'exploded builds' in the measurement. In an exploded build, OpenJDK uses absolute paths to refer to resources, like modules, classes, etc. Also in So there is no issue with |
The following is the performance results for 4 plans (SS, GenCopy, Immix, GenImmix). There is no observable performance difference for the PR. plotty link SemiSpaceGenCopyImmixGenImmix |
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 ScheduleCollection::do_work
, right after the line plan.schedule_collection(worker.scheduler());
, there is an invocation of GCTriggerPolicy::on_gc_start
. See:
fn do_work(&mut self, worker: &mut GCWorker<VM>, mmtk: &'static MMTK<VM>) {
let plan = mmtk.get_plan();
plan.base().set_collection_kind(plan);
plan.base().set_gc_status(GcStatus::GcPrepare);
plan.schedule_collection(worker.scheduler());
// Tell GC trigger that GC started.
// We now know what kind of GC this is (e.g. nursery vs mature in gen copy, defrag vs fast in Immix)
// TODO: Depending on the OS scheduling, other workers can run so fast that they can finish
// everything in the `Unconstrained` and the `Prepare` buckets before we execute the next
// statement. Consider if there is a better place to call `on_gc_start`.
mmtk.get_plan().base().gc_trigger.policy.on_gc_start(mmtk); // HERE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}
}
That line used to be in GCController::do_gc_until_completion
after the controller finished executing ScheduleCollection
. I moved it here when I removed "coordinator work". on_gc_start
should be executed as soon as the kind of GC (nursery or not) is determined, but I had to execute it after plan.schedule_collection
because the GC kind was set inside plan.schedule_collection
. That was inaccurate because as the comment says, other workers may run so fast that they can finish many jobs before we call on_gc_start
With this PR, we can move on_gc_start
between set_gc_status
and plan.schedule_collection
.
I thought about that, but I don't think we can move |
Not actually. p.s. In |
I see, that's true. In this case, we don't even need to know what kind of GC it is. We should be able to call |
Indeed. It can be moved to the beginning of |
I moved the line for |
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
This PR extracts
set_collection_kind
andset_gc_status
from each plan'sschedule_collection
, and calls them directly in theScheduleCollection
work packet. This removes duplicated code, and also makes our implementation consistent with Java MMTk.For generational plans, in
schedule_collection
in each plan, our current code callsrequires_full_heap_collection
first, and then callset_collection_kind
. With the changes in the PR,requires_full_heap_collection
is called afterset_collection_kind
, which is the same as in Java MMTk (super.collectionPhase(phaseId);). The implications are:set_collection_kind
forces a full heap GC, andset_collection_kind
is called beforerequires_full_heap_collection
, we will do a full heap GC in the current GC (which is the expected behavior in Java MMTk).set_collection_kind
may increasecur_collection_attempt
, which makes it more likely to trigger an emergency GC, and makes it more likely to trigger a full heap GC.In summary, we miss some opportunities where we should do a full heap GC. With the changes, we should properly trigger full heap GCs when we should.