Runtime: Can the GetProcessesByName method reduce the number of arrays and Process objects created?

Created on 13 Aug 2020  路  7Comments  路  Source: dotnet/runtime

Description

As written in the code, GetProcessesByName first calls GetProcesses to obtain all processes of the machine, and then filters the process name

        public static Process[] GetProcessesByName(string? processName, string machineName)
        {
            if (processName == null)
            {
                processName = string.Empty;
            }

            Process[] procs = GetProcesses(machineName);
            var list = new List<Process>();

            for (int i = 0; i < procs.Length; i++)
            {
                if (string.Equals(processName, procs[i].ProcessName, StringComparison.OrdinalIgnoreCase))
                {
                    list.Add(procs[i]);
                }
                else
                {
                    procs[i].Dispose();
                }
            }

            return list.ToArray();
        }

But in fact, we can filter the process name in GetProcesses in advance.

        public static Process[] GetProcesses(string machineName)
        {
            bool isRemoteMachine = ProcessManager.IsRemoteMachine(machineName);
            ProcessInfo[] processInfos = ProcessManager.GetProcessInfos(machineName);
            Process[] processes = new Process[processInfos.Length];
            for (int i = 0; i < processInfos.Length; i++)
            {
                ProcessInfo processInfo = processInfos[i];
                processes[i] = new Process(machineName, isRemoteMachine, processInfo.ProcessId, processInfo);
            }
            return processes;
        }

If we do this, we can reduce the allocation length of the Process array and create some Process objects in the GetProcesses method

area-System.Diagnostics.Process tenet-performance up-for-grabs

Most helpful comment

If we want to reduce memory allocation, we may want to filter the process name all the way through the NtProcessInfoHelper.GetProcessInfos, for Windows, where we have SYSTEM_PROCESS_INFORMATION.ImageName:
https://github.com/dotnet/runtime/blob/f4d39134b8daefb5ab0db6750a203f980eecb4f0/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.Win32.cs#L346

and similarly for Linux: https://github.com/dotnet/runtime/blob/6072e4d3a7a2a1493f514cdf4be75a3d56580e84/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.Linux.cs#L187

All 7 comments

Tagging subscribers to this area: @eiriktsarpalis
See info in area-owners.md if you want to be subscribed.

@lindexi is this just a general observation, or is this causing performance impact in your own application?

@danmosemsft this is just a general observation.

@lindexi thanks, but unless something is self-evidently inefficient, we would need perf numbers to motivate increasing the complexity in this way. I will close this: feel free to reopen if you have such numbers. We recommend use of Benchmark.NET. I do agree with @jkotas that I do not think you will see a benefit.

Apologies - I mixed this up with the other perf issue you opened (for registry). I have not evaluated this one.

@lindexi would you like to send a PR?

If we want to reduce memory allocation, we may want to filter the process name all the way through the NtProcessInfoHelper.GetProcessInfos, for Windows, where we have SYSTEM_PROCESS_INFORMATION.ImageName:
https://github.com/dotnet/runtime/blob/f4d39134b8daefb5ab0db6750a203f980eecb4f0/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.Win32.cs#L346

and similarly for Linux: https://github.com/dotnet/runtime/blob/6072e4d3a7a2a1493f514cdf4be75a3d56580e84/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.Linux.cs#L187

Was this page helpful?
0 / 5 - 0 ratings

Related issues

nalywa picture nalywa  路  3Comments

omariom picture omariom  路  3Comments

bencz picture bencz  路  3Comments

jamesqo picture jamesqo  路  3Comments

omajid picture omajid  路  3Comments