-
-
Notifications
You must be signed in to change notification settings - Fork 411
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
Use Vec<T>
for keeping track of gc objects
#3493
Conversation
Test262 conformance changes
|
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #3493 +/- ##
==========================================
- Coverage 44.57% 44.54% -0.03%
==========================================
Files 487 487
Lines 50621 50598 -23
==========================================
- Hits 22563 22539 -24
- Misses 28058 28059 +1 ☔ View full report in Codecov by Sentry. |
Um, I'm pretty sure the point of using intrusive linked lists here is to avoid having live allocations on the GC state. This does make it faster, but consider that the Sample{
let array = []
for (let i = 0; i <= 100000; i++) {
array.push({data: i});
}
}
$boa.gc.collect()
{
let array = []
for (let i = 0; i <= 100000; i++) {
array.push({data: i});
}
}
$boa.gc.collect() Running Maindhat: Total: 248,322,251 bytes in 1,984,424 blocks
dhat: At t-gmax: 53,298,622 bytes in 274,607 blocks
dhat: At t-end: 499,999 bytes in 2,648 blocks This PRdhat: Total: 217,362,347 bytes in 1,984,405 blocks
dhat: At t-gmax: 57,012,374 bytes in 283,328 blocks
dhat: At t-end: 4,678,511 bytes in 2,650 blocks Note how main uses only 500k bytes of heap at the end of the program, while this PR uses 4.5M bytes. |
The alternative would be to resize the |
In that case we can |
Had the same thought 😆 |
Fixed in 685b29d :)
Previous implementation
Current implementation
|
I'd personally keep the current linked list just because it could enable some optimizations in the future; I think CPython uses the pointer as a tagged pointer to store the ref count. Since I'm tending towards not merging this, I'd probably defer the review to @nekevss and @raskad for an unbiased opinion. |
Umm.. Note the "previous implementation" is the previous implementation of this PR (without 685b29d), not main branch, so there is still a pretty nice perf increase. (I should have added a note on it 😅 ). I wanted to show that limiting the capacity allocation does not effect the performance, oddly I saw a very slight improvement (😕)? There is a ~40 score increase in splay from main's imlementation, probably because it creates so many objects, to construct the tree. |
Noted 👍 I still feel it's "wrong" to use allocations to keep track of allocations, so I'd still defer to the rest of the team for more opinions on this. |
I'd tend to agree a bit more with Jedel that using the extra allocation of |
This just moves the memory that was used to track the gc pointers ( Why is this weird? In the future, if we aspire to achieve significant improvements in speed, it may be necessary to develop our own "malloc" and take charge of managing the heap pages ourselves. Perhaps my exposure to a considerable amount of v8/Spidermonkey code and techniques has influenced my perspective of what is weird. Making this proposed change seem normal. 😆 |
Ooh, does V8/SM use dynamic arrays to keep track of allocated memory? If that's the case, it'll remove my uncertainty completely. |
Most of my hesitation here is around the strict provenance and how loading the I agree on the That all being said, I could be wrong. If there's consensus to move forward with this, we can. |
They preallocate a large slabs of memory, they keep track of whats free instead of what is allocated. I think they use an in-place free list. You can find some information here Anyway, I just felt like it was a waste to leave that big of a performance boost. Though I'm totally fine with closing if there is any cause for concern or a consensus has been reached :) @raskad what are your thoughts on this? |
To be honest, I though of this exact change multiple times myself already but was never to confident to actually try it :D I think this is the right step forward. As far as I know, storing gc allocations in one or more continuous blocks of memory is probably the best approach. And starting it out with a simple Vec seems like the most natural solution to me. I'm courious about the strict provenance argument. As far as I know miri has some strict provenance checks correct? @HalidOdat did you run miri on the boa_gc tests with this change? |
Made some research and Spidermonkey uses a mixed architecture of "Zones", which are mini heaps of memory that contain many objects that are tracked using linked lists. Their GC collects at the granularity of zones, and they keep track of the active zones using a I think this should be enough evidence to accept this change. |
Ran it with the MIRIFLAGS="-Zmiri-strict-provenance" cargo +nightly miri test -p boa_gc |
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.
If SM is using a Vec
equivalent and miri
isn't throwing any errors, then I'm fine with moving forward with this.
This does not reduce memory usage, since we still keep a pointer to the gc objects, but instead it reduces the overhead of jumping through the intrusive linked list and also simplifies the gc collection functions.
Benchmarks
Main
PR