summaryrefslogtreecommitdiff
path: root/src/System.Private.CoreLib
diff options
context:
space:
mode:
authorSung Yoon Whang <suwhang@microsoft.com>2019-10-15 22:08:30 -0700
committerGitHub <noreply@github.com>2019-10-15 22:08:30 -0700
commitf2343fb8b9e13bb9a3542e988ad4ae04a621f378 (patch)
tree2854dbddc720f1ff8c5e9d51c2feafacd451f7b1 /src/System.Private.CoreLib
parentc2bb3060555522bfb670ec2012578e8c77eae4da (diff)
downloadcoreclr-f2343fb8b9e13bb9a3542e988ad4ae04a621f378.tar.gz
coreclr-f2343fb8b9e13bb9a3542e988ad4ae04a621f378.tar.bz2
coreclr-f2343fb8b9e13bb9a3542e988ad4ae04a621f378.zip
Improve the performance of Environment.WorkingSet in Windows (#26522) (#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
Diffstat (limited to 'src/System.Private.CoreLib')
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetProcessMemoryInfo.cs30
-rw-r--r--src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems1
-rw-r--r--src/System.Private.CoreLib/shared/System/Environment.Unix.cs19
-rw-r--r--src/System.Private.CoreLib/shared/System/Environment.Windows.cs15
-rw-r--r--src/System.Private.CoreLib/shared/System/Environment.cs24
5 files changed, 65 insertions, 24 deletions
diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetProcessMemoryInfo.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetProcessMemoryInfo.cs
new file mode 100644
index 0000000000..98234b8e6e
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetProcessMemoryInfo.cs
@@ -0,0 +1,30 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+internal partial class Interop
+{
+ internal partial class Kernel32
+ {
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct PROCESS_MEMORY_COUNTERS
+ {
+ public uint cb;
+ public uint PageFaultCount;
+ public UIntPtr PeakWorkingSetSize;
+ public UIntPtr WorkingSetSize;
+ public UIntPtr QuotaPeakPagedPoolUsage;
+ public UIntPtr QuotaPagedPoolUsage;
+ public UIntPtr QuotaPeakNonPagedPoolUsage;
+ public UIntPtr QuotaNonPagedPoolUsage;
+ public UIntPtr PagefileUsage;
+ public UIntPtr PeakPagefileUsage;
+ }
+
+ [DllImport(Libraries.Kernel32, EntryPoint="K32GetProcessMemoryInfo")]
+ internal static extern bool GetProcessMemoryInfo(IntPtr Process, ref PROCESS_MEMORY_COUNTERS ppsmemCounters, uint cb);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems b/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems
index 049a914f76..f9a769e1fd 100644
--- a/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems
+++ b/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems
@@ -1047,6 +1047,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.GetFullPathNameW.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.GetLongPathNameW.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.GetLogicalDrives.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.GetProcessMemoryInfo.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.GetProcessTimes.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.GetSystemDirectoryW.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.GetSystemInfo.cs" />
diff --git a/src/System.Private.CoreLib/shared/System/Environment.Unix.cs b/src/System.Private.CoreLib/shared/System/Environment.Unix.cs
index 9a2af4dfb8..47899cac10 100644
--- a/src/System.Private.CoreLib/shared/System/Environment.Unix.cs
+++ b/src/System.Private.CoreLib/shared/System/Environment.Unix.cs
@@ -444,5 +444,24 @@ namespace System
}
return (int)result;
}
+
+ public static long WorkingSet
+ {
+ 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)
+ {
+ using (currentProcess)
+ {
+ object? result = processType!.GetMethod("get_WorkingSet64")?.Invoke(currentProcess, BindingFlags.DoNotWrapExceptions, null, null, null);
+ if (result is long) return (long)result;
+ }
+ }
+
+ // Could not get the current working set.
+ return 0;
+ }
+ }
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Environment.Windows.cs b/src/System.Private.CoreLib/shared/System/Environment.Windows.cs
index 957d1894a2..e2b0918553 100644
--- a/src/System.Private.CoreLib/shared/System/Environment.Windows.cs
+++ b/src/System.Private.CoreLib/shared/System/Environment.Windows.cs
@@ -119,5 +119,20 @@ namespace System
return builder.ToString();
}
}
+
+ public static unsafe long WorkingSet
+ {
+ get
+ {
+ Interop.Kernel32.PROCESS_MEMORY_COUNTERS memoryCounters = default;
+ memoryCounters.cb = (uint)(sizeof(Interop.Kernel32.PROCESS_MEMORY_COUNTERS));
+
+ if (!Interop.Kernel32.GetProcessMemoryInfo(Interop.Kernel32.GetCurrentProcess(), ref memoryCounters, memoryCounters.cb))
+ {
+ return 0;
+ }
+ return (long)memoryCounters.WorkingSetSize;
+ }
+ }
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Environment.cs b/src/System.Private.CoreLib/shared/System/Environment.cs
index 2b638fde9e..edf1eeeabe 100644
--- a/src/System.Private.CoreLib/shared/System/Environment.cs
+++ b/src/System.Private.CoreLib/shared/System/Environment.cs
@@ -153,30 +153,6 @@ namespace System
}
}
- public static long WorkingSet
- {
- get
- {
- // Use reflection to access the implementation in System.Diagnostics.Process.dll. While far from ideal,
- // we do this to avoid duplicating the Windows, Linux, macOS, and potentially other platform-specific implementations
- // present in Process. If it proves important, we could look at separating that functionality out of Process into
- // Common files which could also be included here.
- Type? processType = Type.GetType("System.Diagnostics.Process, System.Diagnostics.Process, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError: false);
- IDisposable? currentProcess = processType?.GetMethod("GetCurrentProcess")?.Invoke(null, BindingFlags.DoNotWrapExceptions, null, null, null) as IDisposable;
- if (currentProcess != null)
- {
- using (currentProcess)
- {
- object? result = processType!.GetMethod("get_WorkingSet64")?.Invoke(currentProcess, BindingFlags.DoNotWrapExceptions, null, null, null);
- if (result is long) return (long)result;
- }
- }
-
- // Could not get the current working set.
- return 0;
- }
- }
-
private static bool ValidateAndConvertRegistryTarget(EnvironmentVariableTarget target)
{
Debug.Assert(target != EnvironmentVariableTarget.Process);