Skip to content
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

Merged
merged 4 commits into from
Aug 28, 2018

Conversation

rjmholt
Copy link
Contributor

@rjmholt rjmholt commented Aug 23, 2018

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.

{
fileMap.Add(file, new ScriptFile(file, null, this.powerShellContext.LocalPowerShellVersion.Version));
scriptFile = new ScriptFile(
Copy link
Collaborator

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)

Copy link
Contributor Author

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)
Copy link
Collaborator

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);
Copy link
Collaborator

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this seems suspect...

Copy link
Collaborator

@SeeminglyScience SeeminglyScience left a 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 ;)

Copy link
Contributor

@rkeithhill rkeithhill left a 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);
Copy link
Member

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?

Copy link
Contributor Author

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 =>
Copy link
Member

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.

Copy link
Contributor Author

@rjmholt rjmholt Aug 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm game!

Copy link
Contributor Author

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

Copy link
Contributor Author

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

Copy link
Member

@TylerLeonhardt TylerLeonhardt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@TylerLeonhardt
Copy link
Member

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 ;)

pls @rjmholt

@TylerLeonhardt
Copy link
Member

also before this goes in can we merge in the tests PR and rebase from master so CI is happy?

@rjmholt
Copy link
Contributor Author

rjmholt commented Aug 28, 2018

Just tried this change out with Shift-F12 on this function:
https://github.com/PSAppDeployToolkit/PSAppDeployToolkit/blob/c14bbf373bee4823579c378dc4c55e9d75240313/Sources/BetaToolkit/AppDeployToolkitMain.ps1#L388

Before this change:

Found symbol references for Write-FunctionHeaderOrFooter in /home/rob/Documents/Dev/Microsoft/PSAppDeployToolkit/Sources/BetaToolkit/AppDeployToolkitMain.ps1. [800ms]

After this change:

Found symbol references for Write-FunctionHeaderOrFooter in /home/rob/Documents/Dev/Microsoft/PSAppDeployToolkit/Sources/BetaToolkit/AppDeployToolkitMain.ps1. [76ms]

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?

@SeeminglyScience
Copy link
Collaborator

@rjmholt

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.

@rjmholt
Copy link
Contributor Author

rjmholt commented Aug 28, 2018

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.

@rkeithhill
Copy link
Contributor

100 secs on a single file? Yikes!!

@rjmholt
Copy link
Contributor Author

rjmholt commented Aug 28, 2018

@rkeithhill Yeah, it's not good. We've discussed some ways we might be able to optimise it here:
PowerShell/PSScriptAnalyzer#1056

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

CodeLens falls over when a file it's looking at is deleted Intermittent CodeLens crash
4 participants