Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

Improve the performance of Environment.WorkingSet in Windows #26522

Merged
merged 13 commits into from
Sep 12, 2019

Conversation

sywhang
Copy link

@sywhang sywhang commented Sep 5, 2019

This improves the performance of Environment.WorkingSet by calling Win32 API GetProcessMemoryInfo directly to fetch the working set size instead of doing reflection over System.Diagnostics.Process and calling get_workingSet64 which does a bunch of allocations and additional API calls.

On Linux, there is no simple native API to call and we need to parse procfs. However, from the same benchmark, the Linux is much, much faster than Window when we call Environment.WorkingSet so I don't think we need to replace it on Linux. (From my bare bones benchmark, it was ~1000x faster on a same machine).

This fixes #23736.

Copy link
Member

@stephentoub stephentoub left a comment

Choose a reason for hiding this comment

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

Please don't do this. If Environment.WorkingSet is performing poorly, let's fix Environment.WorkingSet, not duplicate its functionality in a private manner.

@sywhang sywhang changed the title Improve the performance of working set counter in Windows Improve the performance of Environment.WorkingSet in Windows Sep 5, 2019
get
{
Type? processType = Type.GetType("System.Diagnostics.Process, System.Diagnostics.Process, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError: false);
if (processType?.GetMethod("GetCurrentProcess")?.Invoke(null, BindingFlags.DoNotWrapExceptions, null, null, null) is IDisposable currentProcess)
Copy link
Member

Choose a reason for hiding this comment

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

Do we need to fix the perf of this one too? How much more expensive is this compared to Windows? Does the cost of this show up in the profiles when you turn on performance counters that call this again and again?

Copy link
Author

Choose a reason for hiding this comment

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

Ideally, yes. But my benchmarks using BenchmarkDotNet suggested that Linux is at a better state than Windows (>10x) so for now I'm fixing Windows first.

Linux:

|     Method |     N |     Mean |    Error |   StdDev | Rank |
|----------- |------ |---------:|---------:|---------:|-----:|
| workingset | 10000 | 143.4 us | 2.520 us | 2.801 us |    1 |

Windows (before the fix):

|     Method |     N |     Mean |     Error |    StdDev | Rank |
|----------- |------ |---------:|----------:|----------:|-----:|
| workingset | 10000 | 1.620 ms | 0.0153 ms | 0.0127 ms |    1 |

In addition to this, the customer requesting this fix is Bing and they are running on Windows.

That being said, the Linux overhead is also huge compared to what we have on Windows after this fix so ideally we'd like to fix it on Linux too:

|     Method |     N |     Mean |     Error |    StdDev |   Median | Rank |
|----------- |------ |---------:|----------:|----------:|---------:|-----:|
| workingset | 10000 | 851.6 ns | 16.916 ns | 34.556 ns | 835.9 ns |    1 |

@sywhang sywhang merged commit 6f8cdbc into dotnet:master Sep 12, 2019
@ViktorHofer
Copy link
Member

ViktorHofer commented Sep 13, 2019

In corefx we currently assert on UWP that Environment.WorkingSet throws a PNSE. With this change an exception isn't thrown anymore. I assume the changed behavior is fine? This is the failing test: https://github.com/dotnet/corefx/blob/47d96f89df41ce18d3ba77b38007ec68f7f66fc6/src/System.Runtime.Extensions/tests/System/EnvironmentTests.cs#L190

@jkotas
Copy link
Member

jkotas commented Sep 13, 2019

Yes, the changed behavior is fine.

sywhang added a commit to sywhang/coreclr that referenced this pull request Oct 15, 2019
…26522)

* Use win32 api directly for workingset counter

* Fix build warnings

* Removing useless code

* more cleanup

* remove size annotation

* remove useless comment

* Move all the changes to Environment.WorkingSet and remove it from RuntimeEventSourceHelper

* removing useless usings

* Use kernel32.dll instead of psapi.dll

* Code review feedback

* Remove newline change

* More code review nits
sywhang added a commit that referenced this pull request Oct 16, 2019
…#27212)

* Use win32 api directly for workingset counter

* Fix build warnings

* Removing useless code

* more cleanup

* remove size annotation

* remove useless comment

* Move all the changes to Environment.WorkingSet and remove it from RuntimeEventSourceHelper

* removing useless usings

* Use kernel32.dll instead of psapi.dll

* Code review feedback

* Remove newline change

* More code review nits
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

WorkingSet runtime counter uses reflection
6 participants