-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Miri: Skip over GlobalAllocs when sweeping #118080
Conversation
17bdf20
to
9fc2c00
Compare
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as abuse.
This comment was marked as abuse.
☔ The latest upstream changes (presumably #118134) made this pull request unmergeable. Please resolve the merge conflicts. |
9fc2c00
to
16c5769
Compare
16c5769
to
8520226
Compare
Some changes occurred to the CTFE / Miri engine cc @rust-lang/miri The Miri subtree was changed cc @rust-lang/miri |
Oh 🤦 I just remembered why I was keeping this as a draft. I wanted to post benchmarks. I'll do that in a few hours. |
pub fn is_alloc_live(&self, id: AllocId) -> Liveness { | ||
if self.memory.alloc_map.contains_key_ref(&id) { | ||
return Liveness::Live; | ||
} |
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.
Note that these might be global. On their first read or write, globals get copied into the alloc_map
, which is needed because we need to convert them from the global provenance type to that of Miri.
So what even is your definition of "global"? "AllocId is in tcx
" or "AllocId is not in memory
"? Those two are not equivalent.
@@ -648,32 +648,27 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' | |||
}; | |||
|
|||
let (_size, _align, alloc_kind) = this.get_alloc_info(alloc_id); |
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.
This does not care about size and align so it should call is_alloc_live
, not get_alloc_info
.
(We probably have more of these across Miri.)
Hm, my first reaction is that I really don't like such global changes. Most places shouldn't care whether something is global or not, and so this pollutes the actually relevant logic with some irrelevant book-keeping. I would strongly prefer if that can be avoided, or at least factored away so as to be completely invisible inside intptrcast and borrow tracking. So the point of this is that |
For allocations which will never deallocated but currently are not referenced in the Machine, the current implementation does two lookups (one into the map of AllocIds referenced in the Machine, then The perf implications of this PR are insignificant for normal operation, so if you don't think we can get the complexity cost down, I think it might make sense to not do this optimization. Running the GC infrequently is very effective for pushing down overheads like this into the noise. But just to point out the value, I derived this optimization originally by studying execution of the
And with this PR, we see:
The 0weak_memory_consistency test has the same change as the |
Those are some pretty impressive wins indeed, albeit for a rather artificial benchmark. How far do you have to increase the GC interval to make the improvement disappear in the noise?
This could be reduced to one lookup by swapping the order in which they are checked. But I suppose that's worse elsewhere? |
☔ The latest upstream changes (presumably #118284) made this pull request unmergeable. Please resolve the merge conflicts. |
Obviated by #118336 |
Global allocations in the interpreter are never deallocated, so their AllocId is always in-use and cannot be removed by the GC. So when we are checking whether an AllocId can be removed, we really want to fast-path out if we know that the AllocId refers to a Global allocation.
In the interpreter we have a few HashMaps that map AllocId to something else, so in all those maps I've stuck a bool alongside the value which is a local cache of "Is this AllocId global".
LiveAllocs::is_live
now also takes a&mut bool
so that it can set the flag if it deduces that the AllocId is in use because it is global.InterpCx::is_alloc_live
now returns a Liveness enum which is alive, dead, or global, so that we can populate local bool if we ever look up whether a Global allocation is live.r? RalfJung
Ideally we could set this flag upon insertion into these maps, but eagerly setting the value for
base_ptr_tag
doesn't seem possible. It's also tempting to pack the bit we need here into AllocId, but users of these maps don't know if they are looking up a GlobalAlloc so we would need Hash+PartialEq that ignores the bit which seems cursed.