-
Notifications
You must be signed in to change notification settings - Fork 97
Improve performance by caching conversion to NormalizedUri #384
Conversation
This conversion is quite expensive to repeat multiple times. Therefore we cache it when creating a NormalizedFilePath so it's only computed once. Making this change causes a benchmark which calls hover 1000 times to go down from 259s to 44s.
NormalizedUri is the primary key type for the debouncer which will have a cached hash in the next haskell-lsp release.
Branch with the change which tracks the haskell-lsp is here - https://github.com/mpickering/ghcide/tree/perf-haskell-lsp |
deriving (Show, Generic, Eq, Ord) | ||
|
||
instance NFData NormalizedUriWrapper where | ||
rnf = rwhnf |
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.
That NFData
instance isn't correct either. Can we just lose it?
@ndmitchell does Shake care about these NFData
instances?
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.
Nevermind, it is fine
Looks good to me! |
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.
Awesome, thank you so much for working on this!
-- | ||
-- This is one of the most performance critical parts of ghcide, do not | ||
-- modify it without profiling. | ||
data NormalizedFilePath = NormalizedFilePath NormalizedUriWrapper Int !FilePath |
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.
Similar question as for the haskell-lsp
PR. Should we make the first two fields or at least the hash strict and unpack it?
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 can see the argument for making the hash strict but not the NormalizedUriWrapper
as that is quite expensive to compute if you never use it.
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 made the hash strict.
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.
Thanks!
* Cache conversion to NormalizedUri from NormalizedFilePath This conversion is quite expensive to repeat multiple times. Therefore we cache it when creating a NormalizedFilePath so it's only computed once. Making this change causes a benchmark which calls hover 1000 times to go down from 259s to 44s. * Use a HashMap rather than a Map for debouncer NormalizedUri is the primary key type for the debouncer which will have a cached hash in the next haskell-lsp release. * NormalizedFilePath: Make the hash strict so it can be unpacked
…hcide#384) * Cache conversion to NormalizedUri from NormalizedFilePath This conversion is quite expensive to repeat multiple times. Therefore we cache it when creating a NormalizedFilePath so it's only computed once. Making this change causes a benchmark which calls hover 1000 times to go down from 259s to 44s. * Use a HashMap rather than a Map for debouncer NormalizedUri is the primary key type for the debouncer which will have a cached hash in the next haskell-lsp release. * NormalizedFilePath: Make the hash strict so it can be unpacked
…hcide#384) * Cache conversion to NormalizedUri from NormalizedFilePath This conversion is quite expensive to repeat multiple times. Therefore we cache it when creating a NormalizedFilePath so it's only computed once. Making this change causes a benchmark which calls hover 1000 times to go down from 259s to 44s. * Use a HashMap rather than a Map for debouncer NormalizedUri is the primary key type for the debouncer which will have a cached hash in the next haskell-lsp release. * NormalizedFilePath: Make the hash strict so it can be unpacked
…hcide#384) * Cache conversion to NormalizedUri from NormalizedFilePath This conversion is quite expensive to repeat multiple times. Therefore we cache it when creating a NormalizedFilePath so it's only computed once. Making this change causes a benchmark which calls hover 1000 times to go down from 259s to 44s. * Use a HashMap rather than a Map for debouncer NormalizedUri is the primary key type for the debouncer which will have a cached hash in the next haskell-lsp release. * NormalizedFilePath: Make the hash strict so it can be unpacked
Two changes in this patch make performance quite a lot better for all actions.
NormalizedUri
fromNormalizedFilePath
NormalizedUri
.The cached
Hashable
instance is in this PR: haskell/lsp#214My benchmark which ran hover 1000 times went down from 259s to 37s including initialisation time. Hovering on large projects is not noticeably faster (1s vs < 0.1s).
Reviewer: @pepeiborra
Note: I removed the Eq/Ord instance from Pepe's original patch because they relied on the hash for comparing equality. There are some hotspots on the latest profile from