-
Notifications
You must be signed in to change notification settings - Fork 108
perf: store thunk data directly in value blocks #2455
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
base: master
Are you sure you want to change the base?
Conversation
This commit fixes a useless indirection when storing a closure/thunk as a value (or, before that, as a term). We would handle this case by storing a Thunk, which is itself of the form `Rc<RefCell<ThunkData>>`. However, value blocks are already reference-counted, so it doesn't make much sense to store an rc-ed pointer into another rc-ed pointer, for no obvious benefit. This commit implements the usual layout for thunks, which is to store directly the mutable thunk data into the value block, removing an indirection and an allocation.
| /// converse isn't true: two thunks can be equal as expressions but have different UID. | ||
| /// | ||
| /// In practice, the UID is currently the underlying `Rc` pointer value. | ||
| pub fn uid(&self) -> usize { |
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.
uid() seemed to not be used anymore.
|
This wins a noticeable chunk of memory usage, but is around 2% slower on the OPL benchmark. Investigating a bit. I can see with cachegrind that the instruction cache has different stats (otherwise there seems to be slightly less branches, slightly less mispredictions, and slightly less data access/data cache misses), so maybe it's just noise from the change of layout of the binary 🤷♂️ Another possibility is that the improvement is nullified by our less optimal implementation of |
|
Ok, after a round of optimizing a bit the reference counting part of |
This PR fixes a useless indirection when storing a closure/thunk as a value (or, before that, as a term). We would handle this case by storing a
Thunk, which is itself of the formRc<RefCell<ThunkData>>. However, value blocks are already reference-counted, so it doesn't make much sense to store an rc-ed pointer into another rc-ed pointer for no obvious benefit.This commit implements the usual layout for thunks, which is to store directly the mutable thunk data into the value block, removing an indirection and an allocation.
There is the question of how to define
Thunk, now that it is the same as aNickelValueor aValueBlockRc, just one specific case. I started by performing operations onvalue::ThunkData := RefCell<lazy::ThunkData>first, but some operations do require not only the content, but the originalRcpointer (typically, for cloning or for testing physical equality). In the end, I madeThunka smart constructor/transparent wrapper aroundNickelValue, which encodes at the type level that we know that this value is a block of type thunk.