0

I'm trying to get the sizes of the shareable and shared working sets of a process.

This is the code that I use:

internal static unsafe WorkingSetInfo? GetWorkingSetInfo(SafeProcessHandle processHandle)
{
    Settings.Log.Info("Called method: GetWorkingSetInfo");
    uint size = 16;
    void* pointer = Alloc(size);
    int error;
    Settings.Log.Debug("Retrieving info on working set...");
    bool result = QueryWorkingSet(processHandle, pointer, size);
    while (!result)
    {
        error = GetLastPInvokeError();
        if (error is ERROR_BAD_LENGTH)
        {
            size *= 2;
            pointer = Realloc(pointer, size);
            result = QueryWorkingSet(processHandle, pointer, size);
        }
        else
        {
            Settings.Log.DebugFormat("Failed to retrieve info on working set: {0} ({1})", GetLastPInvokeErrorMessage(), error);
            Free(pointer);
            return null;
        }
    }
    PSAPI_WORKING_SET_INFORMATION info = new();
    ulong* dataPointer = (ulong*)pointer;
    info.NumberOfEntries = new(*dataPointer);
    dataPointer += 1;
    info.WorkingSetInfo = new nuint[info.NumberOfEntries];
    for (var i = 0; i < info.NumberOfEntries.ToUInt32(); i++)
    {
        info.WorkingSetInfo[i] = new(*dataPointer);
        dataPointer += 1;
    }
    Free(pointer);
    uint pageSize = GetMemoryPageSize();
    return new(info, pageSize);
}

This code works correctly, but it is also inefficient. Whenever it runs, the CPU usage of my process rises to around 30% (the average is 10% when it does not run).

Is there a way to optimize it, or an alternate way to get the data (I use the QueryWorkingSet function)?

I can use the Native API if there is no alternative.

1 Answer 1

-1

GetProcessMemoryInfo is well documented making it easier to find support and examples, QueryWorkingSet is less commonly used. GetProcessMemoryInfo provides a broader range of memory-related statistics through the PROCESS_MEMORY_INFO struct while QueryWorkingSet focuses mainly on the basic working set information.

[DllImport("psapi.dll", SetLastError = true)] 
static extern bool GetProcessMemoryInfo(IntPtr processHandle, out 
PROCESS_MEMORY_INFO mem_info, uint size); 
[StructLayout(LayoutKind.Sequential)] 
public struct PROCESS_MEMORY_INFO 
{
    static readonly uint Size = (uint)Marshal.SizeOf<PROCESS_MEMORY_INFO>();
    public uint cb; 
    public uint PageFaultCount; 
    public ulong PeakWorkingSetSize; 
    public ulong WorkingSetSize; 
    public ulong QuotaPeakPagedPoolUsage; 
    public ulong QuotaPagedPoolUsage; 
    public ulong QuotaPeakNonPagedPoolUsage; 
    public ulong QuotaNonPagedPoolUsage; 
    public ulong PagefileUsage; 
    public ulong PeakPagefileUsage; 
    public ulong PrivateUsage;
    public static bool GetProcessInfo(Process proc, out PROCESS_MEMORY_INFO mem_info)
    {
        return GetProcessMemoryInfo(proc.Handle, out mem_info, Size);               
    }
}

Then to use :

static void Main(string[] args)
{
    Process proc = Process.GetCurrentProcess();
    if (PROCESS_MEMORY_INFO.GetProcessInfo(proc, out PROCESS_MEMORY_INFO mem_info))
    {
        ulong workingSetSize = mem_info.WorkingSetSize;
        ulong peakWorkingSetSize = mem_info.PeakWorkingSetSize;
        ulong sharableWorkingSetSize = workingSetSize - mem_info.PrivateUsage;
        Console.WriteLine($"Working Set Size : {workingSetSize}");
        Console.WriteLine($"Peak Working Set Size : {peakWorkingSetSize}");
        Console.WriteLine($"Shareable Working Set Size : {sharableWorkingSetSize}");
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

A quality answer must identify the core issue and explain why and how the proposed solution addresses it.
The update merely provides unfounded opinion and answers a question that hasn't been asked.
The GetProcessMemoryInfo function provides the total size of the working set, I need to know the shareable and the shared portion of it. As far as I could find. this information is given only by QueryWorkingSet or NtQueryVirtualMemory (the output of which is the same).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.