-
Notifications
You must be signed in to change notification settings - Fork 5.4k
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
Add AST module caching support for LSP #5251
Conversation
Really nice work, the speed up is massive!
Calling it on every keystroke certainly seems excessive, even on every couple keystrokes. I think it could be worth thinking about having a memory size heuristics-based system instead, and calling it on idle time so it's less perceptible to the user. |
Very nice. It probably needs to be tuned further, but it's a great start and much cleaner than I would have expected for something like this. |
Great, I'll start think about a nice heuristic to call gc from. |
49e6fa7
to
2faf4d5
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.
Amazing performance improvement!
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.
Overall looks great, though it seems some of the type engine insertions have a None
source id. As far as I can tell, that means we won't track those, so we won't be able to GC them, right? Assuming that's the case, something we should look into improving in the future.
ac1e23b
to
d78edbe
Compare
Good question, at the top of the type engines let source_id = source_id.map(Clone::clone).or_else(|| info_to_source_id(&ty)); If it's None then we try to map the type_info to a reserved source id. /// Maps specific `TypeInfo` variants to a reserved `SourceId`, returning `None` for non-mapped types.
fn info_to_source_id(ty: &TypeInfo) -> Option<SourceId> {
match ty {
TypeInfo::Unknown
| TypeInfo::UnsignedInteger(_)
| TypeInfo::Numeric
| TypeInfo::Boolean
| TypeInfo::B256
| TypeInfo::RawUntypedPtr
| TypeInfo::RawUntypedSlice
| TypeInfo::StringSlice
| TypeInfo::Contract
| TypeInfo::StringArray(_)
| TypeInfo::Array(_, _) => Some(SourceId::reserved()),
TypeInfo::Tuple(v) if v.is_empty() => Some(SourceId::reserved()),
_ => None,
}
} This way we don't clear types that are shared between modules, and type_info variants that can hold spans are allowed to be None, thus can be cleared safely. |
I'm now only calling it on every 10th keystroke. Unfortunately we can't call it during idle as this would remove internal types needed for doing goto def, hover etc in the users workspace. |
hmm calling it on every 10th keystroke is causing CI to run out of memory. I'll open an issue and we can work on this optimisation in a follow up PR. |
6ef9da2
to
610e35d
Compare
## Description Enables a did_change stress test with random wait times between each trigger to emulate random key typing. This then internally kicks off compilation and triggers garbage collection every 3 keystrokes. I had intended to include this test when garbage collection was implemented in #5251. However, at that time, we were only performing GC every 10th keystroke and it was overloading the stack in CI. Now that we have reduced this to every 3rd keystroke it seems to be fine for CI. Unfortunately, this test wasn't running to catch a bug that slipped through in #5306. As such, this PR currently allows a way for us to reproduce this error but won't be able to pass CI until the underlying issue is resolved. P.S.: This also adds a temporary fix where we retain elements without a source id. This is tantamount to leaking them but seems preferable to disabling the GC altogether. --------- Co-authored-by: xunilrj <[email protected]> Co-authored-by: IGI-111 <[email protected]>
Description
This PR supersedes #4988 and builds on backend work done by @tritao in #4733.
A new
ModuleId
is created for each compiled module. TheSourceId
type now also stores theModuleId
that was used to create it. This allows us to perform garbage collection on types in the Declaration and Type engines that refer the provided module.This method isn't super cheap to call. My tests had this averaging at 54ms. We are currently performing garbage collection on every key stroke in LSP. We should look to have another metric such as only clearing once every 20 keystrokes or so in the future.
I ran benchmarking on recompiling the
doc_comments
example 20 times to simulate rapid keystrokes during coding. Here are the results.A speed up of 1835.49% is certainly great, yet 4.6 seconds still sounds like an eternity. Still have lots of room to improve but this should improve our current system dramatically.
closes #4994
Checklist
Breaking*
orNew Feature
labels where relevant.