-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
.ProcessName should use QueryFullProcessImageNameW or GetProcessImageFileNameW #55685
Comments
Tagging subscribers to this area: @dotnet/area-system-diagnostics-process Issue DetailsOn Windows, .ProcessName should use QueryFullProcessImageNameW or GetProcessImageFileNameW. Presently it used NtQuerySystemInformation(SystemProcessInformation). The problem with NtQuerySystemInformation(SystemProcessInformation) is:
unless you call .ProcessName prior to termination to populate the CLR's cache. We have actual code like this, causing us much grief, because..complicated reasons.
|
Seems reasonable, if it works in all the same places. Do you want to offer a PR, @jaykrell ? |
I wanted to implement the feature but I do not have an industry experience with calling C++ Win32 codes from C#, so I will just leave where things are for people who will implement this in the future if this is indeed the way to go to fetch ProcessName. ProcessName exists in https://github.com/dotnet/runtime/blob/a5842801e0c3fef66532da584528905c88b88f5b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.cs
ProcessName ensures that we have _processInfo not be to null. If this is null, EnsureState will make following calls,
and for Windows, that goes to this file runtime/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.Windows.cs Line 61 in a584280
This is where NtProcessManager will call the problematic call NtQuerySystemInformation from following code runtime/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.Win32.cs Line 255 in a584280
In short, OP doesn't want to call NtQuerySystemInformation in the first place, just to get ProcessName. I am curious about how the benchmark would look by skipping NtQuerySystemInformation. |
Hi - I'm happy to work on this one. |
After applying this change, getting the process name and working set is much quicker (relatively speaking) and allocates less memory. Benchmarks below. It appears that the associated PR addresses one of @jaykrell 's issues in that However, It doesn't satisfy the requirement that BenchmarksBenchmarkDotNet=v0.13.1, OS=Windows 10.0.22000
Intel Core i7-7700K CPU 4.20GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical cores
.NET SDK=7.0.100-alpha.1.21467.19
[Host] : .NET 5.0.10 (5.0.1021.41214), X64 RyuJIT
Job-YJXSLY : .NET 7.0.0 (42.42.42.42424), X64 RyuJIT
Job-NVCLTE : .NET 7.0.0 (42.42.42.42424), X64 RyuJIT
IterationCount=15 LaunchCount=2 WarmupCount=10
Legend:
|
On Windows, .ProcessName should use QueryFullProcessImageNameW or GetProcessImageFileNameW.
Presently it used NtQuerySystemInformation(SystemProcessInformation).
The problem with NtQuerySystemInformation(SystemProcessInformation) is:
It is tremendously slower, returning all information about all processes,
instead of just the name, for one process. This is pretty obviously terrible, unless there are very few processes, and perhaps if you only have the process id and not a handle already (two syscalls, open and query). (Too bad Windows doesn't allow query by id to cut the cost.) Enum also has an advantage, sometimes, like, if you actually want more information than just the name. But generally it seems silly.
It does not work with terminated processes, which NtQuerySystemInformation(SystemProcessInformation) omit.
For example, you cannot have a generic:
WriteLine("The process {0} ended", process.ProcessName);
unless you call .ProcessName prior to termination to populate the CLR's cache. Such order/cache-sensitivity is also fragile but maybe ok. And that is not even possible: .NET does not expose creating processes suspended, so you will always race with a fast process that terminates quickly. So
.ProcessName
is all but unusable. We are removing our uses pretty thoroughly as a result. Though it is ok on current process, which will never be terminated.We have actual code like this, causing us much grief, because..complicated reasons (we actually run mostly on an alternate implementation of NT, which was enumerating terminated processes, which mostly masked these problems, but not entirely; the problem is worse on native NT).
We are going to reduce our uses of process.ProcessName as a result.
The text was updated successfully, but these errors were encountered: