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

Retrieve productVersion using informational version attribute in AmsiUtils.Init() #15527

Merged
merged 5 commits into from
Jun 14, 2021
Merged

Retrieve productVersion using informational version attribute in AmsiUtils.Init() #15527

merged 5 commits into from
Jun 14, 2021

Conversation

Fs00
Copy link
Contributor

@Fs00 Fs00 commented Jun 5, 2021

PR Summary

This PR slightly improves PowerShell start-up performance on Windows by using AssemblyInformationalVersionAttribute in AmsiUtils.Init to retrieve PowerShell product version instead of ProcessModule.FileVersionInfo, which is notably slower.
Also, the code that handled possible errors coming from ProcessModule.FileVersionInfo has been removed.

Here is the startup performance difference before and after the PR (launched Measure-Command { .\pwsh -noprofile -c exit } 15 times on a Release build):

master branch:
356,89, 357,19, 356,40, 362,44, 354,41, 355,71, 359,56, 358,05, 350,51, 365,41, 356,74, 357,24, 357,06, 353,06, 353,05
Best: 350,51 ms
Worst: 365,41 ms
Average: 356,91 ms

This PR:
358,31, 347,59, 350,51, 352,66, 348,42, 351,90, 350,34, 354,94, 351,55, 339,00, 344,30, 345,26, 347,64, 351,45, 343,43
Best: 339,00 ms
Worst: 358,31 ms
Average: 349,15 ms

Contributes to #14268.

PR Context

This chance for optimization has been discovered by @iSazonov in #14332 (comment).

PR Checklist

@ghost ghost assigned daxian-dbw Jun 5, 2021
@iSazonov
Copy link
Collaborator

iSazonov commented Jun 6, 2021

Since it is about startup performance please share perf results for just startup. Either Measure-Command { .\pwsh -noprofile -c exit } or PerfView.

@iSazonov iSazonov added the CL-Performance Indicates that a PR should be marked as a performance improvement in the Change Log label Jun 6, 2021
@Fs00
Copy link
Contributor Author

Fs00 commented Jun 6, 2021

Here are the results in milliseconds of running Measure-Command { .\pwsh -noprofile -c exit } on a debug build 15 times:

master branch:
854,19, 807,08, 817,18, 804,88, 820,26, 810,25, 817,35, 829,89, 804,71, 804,96, 809,28, 815,76, 811,47, 810,23, 800,47
Best: 800,47 ms
Worst: 854,19 ms
Average: 814,53 ms

This PR:
785,93, 788,26, 795,68, 786,38, 789,25, 792,89, 791,65, 806,51, 781,68, 791,21, 796,45, 796,87, 791,29, 785,23, 787,25
Best: 781,68 ms
Worst: 806,51 ms
Average: 791,10 ms

@iSazonov
Copy link
Collaborator

iSazonov commented Jun 6, 2021

on a debug build 15 times:

Please do all perf test on Release ( Start-PSBuild -Configuration Release -CrossGen)

@Fs00
Copy link
Contributor Author

Fs00 commented Jun 7, 2021

Same test done on Release build:

master branch:
356,89, 357,19, 356,40, 362,44, 354,41, 355,71, 359,56, 358,05, 350,51, 365,41, 356,74, 357,24, 357,06, 353,06, 353,05
Best: 350,51 ms
Worst: 365,41 ms
Average: 356,91 ms

This PR:
358,31, 347,59, 350,51, 352,66, 348,42, 351,90, 350,34, 354,94, 351,55, 339,00, 344,30, 345,26, 347,64, 351,45, 343,43
Best: 339,00 ms
Worst: 358,31 ms
Average: 349,15 ms

@iSazonov
Copy link
Collaborator

iSazonov commented Jun 7, 2021

@Fs00 Thanks for perf test sharing! Please add this in the PR description.

@iSazonov iSazonov requested a review from PaulHigin June 7, 2021 07:14
// (This has occurred during Exchange set up).
hostname = GetProcessHostName(currentProcess.ProcessName);
}
string appName = string.Concat("PowerShell_", Environment.ProcessPath, "_", PSVersionInfo.ProductVersion);
Copy link
Contributor

Choose a reason for hiding this comment

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

Can 'Environment.ProcessPath' throw? We should have a try/catch here so that AMSI is always initialized.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, I think a generic Exception, and then create the default hostname as before.

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've added a catch block as you requested. I kept using PSVersionInfo.ProductVersion in the catch block (before the PR a placeholder version of 0.0.0.0 was used) since we can safely assume that it will never throw anything.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Btw, I'm a bit uncertain on using Process.ProcessName as a "safe" fallback - it doesn't look much safer than Environment.ProcessPath given that it could potentially throw an InvalidOperationException (https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.process.processname?view=net-5.0#exceptions).

Copy link
Contributor

Choose a reason for hiding this comment

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

Good point, but since it is basically the same as before at least we don't introduce a possible regression.

Copy link
Member

Choose a reason for hiding this comment

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

If the assumption is that Environment.ProcessPath may throw while PSVersionInfo.ProductVersion will never throw, then a comment should be added in the catch block to call this out.
[edited] comment added.

@ghost ghost added Waiting on Author The PR was reviewed and requires changes or comments from the author before being accept and removed Waiting on Author The PR was reviewed and requires changes or comments from the author before being accept labels Jun 10, 2021
Copy link
Contributor

@PaulHigin PaulHigin left a comment

Choose a reason for hiding this comment

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

LGTM

@ghost ghost added the Waiting on Author The PR was reviewed and requires changes or comments from the author before being accept label Jun 14, 2021
@iSazonov
Copy link
Collaborator

Not for the PR but while we are here - what do you think about using new c# feature - source generator - for getting ProductVersion?

@daxian-dbw
Copy link
Member

@iSazonov That sounds like a nice thing to try. Not just the product version, any reflection tasks that can be deterministically done at build time can be considered to be lifted to the source generator.

@daxian-dbw daxian-dbw merged commit a70f915 into PowerShell:master Jun 14, 2021
@Fs00
Copy link
Contributor Author

Fs00 commented Jun 14, 2021

Thanks for merging!

@ghost ghost removed the Waiting on Author The PR was reviewed and requires changes or comments from the author before being accept label Jun 14, 2021
@daxian-dbw
Copy link
Member

@Fs00 Thanks for your contribution!

@ghost
Copy link

ghost commented Jun 17, 2021

🎉v7.2.0-preview.7 has been released which incorporates this pull request.:tada:

Handy links:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CL-Performance Indicates that a PR should be marked as a performance improvement in the Change Log
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants