Skip to content

Conversation

@iSazonov
Copy link
Collaborator

@iSazonov iSazonov commented Nov 28, 2020

PR Summary

At startup we create a temp file with name based on Datetime.Now.ToString().
It is very slow - ~14ms.
We have no need to use human date format for the temp file.

The fix is to use Datetime.UtcNow().Ticks.ToString() Environment.TickCount64:

  • Environment.TickCount64 is significantly faster Datetime.Now() - it is intrinsic and no need to evaluate local time.
  • Ticks is long type and Environment.TickCount64.ToString() is very fast. Datetime.ToString() is slow because it involves Calendar.

Perf win is ~10-30 ms.

Before
image

After
image

PR Context

Tracking issue #14268

PR Checklist

@iSazonov iSazonov added the CL-Performance Indicates that a PR should be marked as a performance improvement in the Change Log label Nov 28, 2020
@iSazonov iSazonov requested a review from TravisEz13 as a code owner November 28, 2020 20:23
// with no content. So create a scratch file and test on that.
string dtAppLockerTestFileContents = AppLockerTestFileContents + DateTime.Now;
string dtAppLockerTestFileContents = AppLockerTestFileContents + DateTime.UtcNow.Ticks;
IO.File.WriteAllText(testPathScript, dtAppLockerTestFileContents);
Copy link
Contributor

Choose a reason for hiding this comment

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

It seems the file name does not depend on the DateTime, but rather the file contents. So maybe we want to keep human date format

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The file is created for automatic testing - no humans see and read the file.

Copy link
Contributor

Choose a reason for hiding this comment

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

no humans see and read the file.

Perhaps it is for debugging purposes.

Actually, if no humans see the file do we require the datetime to be written in any form at all?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I don't know. I am only resolving the perf issue. I can only guess it is how AppLocker works. Perhaps @TravisEz13 or @PaulHigin could add more information.

Copy link
Member

Choose a reason for hiding this comment

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

@TravisEz13 and @PaulHigin, can you please comment on whether we need DateTime to be added to the file content at all?

Copy link
Contributor

Choose a reason for hiding this comment

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

The DateTime was included to add some randomness to the file contents. I think we still need it, but could change it to some other random value if computing it is quicker than DateTime.

Copy link
Member

Choose a reason for hiding this comment

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

@iSazonov Maybe replacing DateTime.Now.Ticks with Environemnt.TickCount?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@daxian-dbw I have no objections. I see Environment.TickCount64 - maybe use it?

Copy link
Member

Choose a reason for hiding this comment

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

That sounds fine to me, go ahead.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done. The PR description has been updated too.

// AppLocker fails when you try to check a policy on a file
// with no content. So create a scratch file and test on that.
string dtAppLockerTestFileContents = AppLockerTestFileContents + DateTime.Now;
string dtAppLockerTestFileContents = AppLockerTestFileContents + DateTime.UtcNow.Ticks;
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
string dtAppLockerTestFileContents = AppLockerTestFileContents + DateTime.UtcNow.Ticks;
string dtAppLockerTestFileContents = AppLockerTestFileContents + DateTime.UtcNow.ToString("u");

Copy link
Contributor

Choose a reason for hiding this comment

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

I took real world measurements using PerfView 😋

It seems my suggested change is not much of an improvement, I measured 8ms for the code line.

I also measured the original code line and it was 14ms, same as your measurement.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

DateTime.UtcNow is more fast - it does not read current user time zone and does not convert to local time.

@iSazonov iSazonov requested a review from PaulHigin November 29, 2020 16:29
@xtqqczze
Copy link
Contributor

It is very slow - ~14ms.

Is this a release build?

Running a microbenchmark, Datetime.Now.ToString() takes ~1us!

@iSazonov
Copy link
Collaborator Author

It is very slow - ~14ms.

Is this a release build?

Running a microbenchmark, Datetime.Now.ToString() takes ~1us!

Yes, it is release build. And it is startup scenario - cold start (.Net runtime loads Calendar data from OS and initializes internal structures - you can see this in attached trace file.). If you run BenchmarkDotNet it is warm start.

@daxian-dbw daxian-dbw merged commit ea3036d into PowerShell:master Dec 4, 2020
@daxian-dbw daxian-dbw added this to the 7.2.0-preview.2 milestone Dec 4, 2020
@iSazonov iSazonov deleted the perf-startup-datetime branch December 4, 2020 17:28
@ghost
Copy link

ghost commented Dec 15, 2020

🎉v7.2.0-preview.2 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.

4 participants