-
Notifications
You must be signed in to change notification settings - Fork 223
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
Fix codelens crash when a file does not exist #732
Fix codelens crash when a file does not exist #732
Conversation
{ | ||
fileMap.Add(file, new ScriptFile(file, null, this.powerShellContext.LocalPowerShellVersion.Version)); | ||
scriptFile = new ScriptFile( |
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.
Oh? This doesn't try to pull an existing ScriptFile
instance? That explains why find references code lens is slow...
Don't know if you want to try this in this PR, but if this could be replaced with Workspace.GetFile()
it would speed up finding references significantly. Right now it's only looking at the cache for files that are explicitly referenced (which is pretty rare)
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.
Yeah I was a bit skeptical of that constructor. I'll see if changing it over works
} | ||
|
||
IEnumerable<string> allFiles = workspace.EnumeratePSFiles(); | ||
foreach (string file in allFiles) |
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.
Possibly inline workspace.EnumeratePSFiles()
if allFiles
is not used somewhere down the line.
var allFiles = workspace.EnumeratePSFiles(); | ||
foreach (var file in allFiles) | ||
// We want to look for references first in referenced files, hence we use ordered dictionary | ||
var fileMap = new OrderedDictionary(StringComparer.OrdinalIgnoreCase); |
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 know this is existing code, but wouldn't this be an issue on Linux?
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.
Yeah, this seems suspect...
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.
LGTM. The difference that ScriptFile
change will make is nuts. I have no doubt that was a big part of why that code lens is so slow.
Might be worth doing some before and after benchmarks with a workspace that has something massive like the PSAppDeploy Toolkit sitting in it. Would make for some exciting release notes ;)
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.
LGTM
{ | ||
fileMap.Add(file, new ScriptFile(file, null, this.powerShellContext.LocalPowerShellVersion.Version)); | ||
scriptFile = workspace.GetFile(file); |
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 is the change that will increase perf, yeah @SeeminglyScience?
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.
Yeah that constructor for ScriptFile
(which is now unused, but is public, so...) does a call to File.ReadAllText()
-- so it always reads off the file system. I'm always averse to something like touching the filesystem in a constructor (and don't really understand why it's done in this constructor, since there's another one that takes a full string), but the real problem is that it's likely we already have the script file contents loaded, and if we don't, this will cache them too
foundSymbol, | ||
CmdletToAliasDictionary, | ||
AliasToCmdletDictionary) | ||
.Select(reference => |
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.
did you want to try to clean up the LINQ usage here? We can call that out of scope if you want.
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'm game!
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 remember when I hit this before I went and searched if we can avoid the closure allocation by turning this into a static (or instance...) method call, but I didn't find any good information on it... Would be nice if we could retain the readable composability of LINQ
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.
Actually, I'll open a new PR on the LINQ refactoring here, since there are other methods that would benefit. I'll see if I can do a quick benchmark before we merge
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.
LGTM!
pls @rjmholt |
also before this goes in can we merge in the tests PR and rebase from master so CI is happy? |
Just tried this change out with Shift-F12 on this function: Before this change:
After this change:
10x speedup for finding 268 references of a function defined in a 9000 line file. More importantly, doing that before the change makes the whole editor feel very sluggish -- I think that's a consequence of something qualitatively worse than more processing or allocations, like maybe open file handles accruing? |
Do you have the code lens on? If so, this isn't just running when you manually hit find references. This is running every single document edit. Reparsing all those files just about every key press... general sluggishness is no surprise. This is going to make a lot of people happy. That difference is incredible. |
Yes CodeLens on and all. Just mean that it's not just CodeLens that sped up, even though that's what I measured; ScriptAnalysis on that file took something insane like 100 seconds, but fixing the CodeLens issue seems to have relieved much more pressure. |
100 secs on a single file? Yikes!! |
@rkeithhill Yeah, it's not good. We've discussed some ways we might be able to optimise it here: |
Fixes PowerShell/vscode-powershell#1471 and fixes #718.
If a file is removed when the reference symbols are being parsed, it will cause an exception to be thrown. Now if that file does not exist, we just skip it.