-
Notifications
You must be signed in to change notification settings - Fork 163
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
Reduce memory usage by deduplicating type information #649
base: master
Are you sure you want to change the base?
Reduce memory usage by deduplicating type information #649
Conversation
✅ Deploy Preview for salsa-rs canceled.
|
CodSpeed Performance ReportMerging #649 will not alter performanceComparing Summary
|
2ecdea8
to
13ecc36
Compare
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 love the idea, but I'm finding myself a bit confused-- we have some tech debt here in that the mdbook is not complete or up-to-date, I'm realizing that I wish it were, because I'd love to read an mdbook update explaining the data structure(s) here. It feels like we could be more efficient still, but I've probably just not fully brought everything back in cache
13ecc36
to
994285d
Compare
@nikomatsakis I addressed your comments. |
The benchmark regressions are a bit concerning (as high as 8%). Do we understand where they come from? |
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 wonder, could we maybe store the types info in the corresponding Page
instead? Then we only have duplication of type info among pages which is neglible while not having to go through the ingredient on lookups. It would also keep more info (for drop and the like) localized
Hmm... If we share it in an |
I don't quite follow here--I'll try to make time tomorrow to review this PR. I'm still finding myself a bit confused about what type information exactly we are deduplicating and where. |
994285d
to
e92d921
Compare
@Veykril I implemented your suggestion to store the types on the page. |
1abc1d8
to
793c14b
Compare
@MichaReiser I've investigated the perf regressions and I think they should be fixed now. |
Thanks. The regression now seems to be specific to benchmarks where we primarily create elements. Can we try to optimize that code path as well (a 18% regression is rather significant) |
@MichaReiser I was referring to that regression, I think I fixed it. |
@ChayimFriedman2 Hmm, in that case I'm unsure if the underlying problem was addressed because the codspeed benchmark still show an 18% regression. |
@MichaReiser It wasn't reran back then, now it shows an 11% regression. I'll see if I can shrink it even more. |
I think the benchmarks are flawed. They re-create the ingredients on every iteration, which is very much not like real-world usages which create the ingredient once. I'll put a PR to fix this. |
793c14b
to
4a69972
Compare
OK, after #667 it shows there is no perf regression. |
@ChayimFriedman2 needs rebase |
6e5346f
to
681547d
Compare
@nikomatsakis Rebased. |
/// Access the [`MemoTable`] for this slot. | ||
/// | ||
/// # Safety | ||
/// | ||
/// You must have mutable access to the slot. | ||
unsafe fn memos_no_revision(&self) -> &MemoTable; |
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.
Then why does this not just take &mut self
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.
Problems with the borrow checker when calling Page::get()
borrows the entire page then we cannot access Page::memo_types
.
fn memos_mut(&mut self, slot: SlotIndex) -> &mut MemoTable { | ||
self.get_mut(slot).memos_mut() | ||
fn memos_mut(&mut self, slot: SlotIndex) -> MemoTableWithTypes<'_> { | ||
// SAFETY: We have a `&mut` reference. | ||
let memos = unsafe { self.get(slot).memos_no_revision() }; |
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 change seems unnecessary to me, we can just use get_mut
and keep the memos_mut
accessor as before
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.
But we need to attach the types to it anyway. I can change create a new type MemoTableWithTypesMut
, but this just seems unnecessary. And given it does not return a mutable reference anymore, memos_mut()
seems inappropriate name now.
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 mind the name change, I was more raising this regarding the unnecessary unsafe block. There is no reason to decay the mutable references in this call chain to an immutable one, doing so results in this extra unsafe that isn't really necessary otherwise
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.
Ah, given your other comment to my review I guess that would require duplicating the function for mutability
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.
What do you mean by
duplicating the function for mutability
?
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.
Problems with the borrow checker when calling
Page::get()
borrows the entire page then we cannot accessPage::memo_types
.
I interpreted this as you'd needing to keep the current version for the borrowck issue either way
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.
No, what I meant is that if I this function takes &mut self
, then Page.get_mut().memos_mut()
clashes with Page.memo_types
, leading to a borrowck error.
246d80e
to
4eea15f
Compare
It seems the perf regression is back :( |
We were storing the type information, 3 words wide, for each memo in each slot, while it is always constant wrt. the ingredient (different slots of the same ingredients will always have the same memos in the same order). This introduces some more unsafety, and the result wasn't as fast so I also had to use some lock-free structures, but the result is worth it: this shaves off 230mb from rust-analyzer with new Salsa.
4eea15f
to
fd9cfb8
Compare
@MichaReiser I rebased and now they're at 5% max. It's hard to investigate because codspeed doesn't identify the same methods, so I don't know what is the cause, but the 8% I'm pretty sure was measurement error or something like that (e.g. it showed a regression for |
The benchmarks have been fairly stable after @Veykril made some changes. That's why I'm not convinced that they're outright wrong. Have you tried recording a profile locally and e.g. comparing them in firefox-profiler? |
There does seem to be some noise still left as my rebased #710 version reports fairly different perf changes now (though I don't think the PR here is entirely noise) |
Rebasing does change the base to which codspeed reports the performance. So that makes sense to some extend. What's interesting is that the perf results are very stable for e.g. https://codspeed.io/salsa-rs/salsa/branches/Veykril%3Aveykril%2Fpush-orlktsrpwzrv |
I'm trying to investigate the regressions locally now. |
The benchmark regressions seem unavoidable (I also suspect part of them is noise), and they are not large. The main reason is having two different |
We were storing the type information, 3 words wide, for each memo in each slot, while it is always constant wrt. the ingredient (different slots of the same ingredients will always have the same memos in the same order). This introduces some more unsafety, and the result wasn't as fast so I also had to use some lock-free structures, but the result is worth it: this shaves off 230mb from rust-analyzer with new Salsa.