You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取运行中C#应用的原生内存使用量(类似jcmd细粒度数据)

获取C#应用的非托管内存使用量(等价jcmd VM.native_memory非堆部分)

一、应用内部获取(可作为追踪指标)

1. 非托管内存总量计算

通过进程内存数据减去托管堆内存,得到近似的非托管内存总量:

using System.Diagnostics;

public static long GetUnmanagedMemoryTotal()
{
    var process = Process.GetCurrentProcess();
    // 进程私有内存总量(包含托管堆、非托管堆、加载模块等)
    long privateMemory = process.PrivateMemorySize64;
    // 强制GC后获取托管堆已提交的总内存,结果更准确
    long managedMemory = GC.GetTotalMemory(true);
    // 非托管内存总量(近似值)
    return privateMemory - managedMemory;
}

注:该结果包含CLR自身的非托管结构、第三方非托管DLL内存等,是进程级非托管内存的近似统计,满足总量追踪需求。

2. 精确追踪Marshal.AllocHGlobal类分配

如果核心目标是追踪Marshal.AllocHGlobal/Marshal.FreeHGlobal这类手动非托管分配,可以封装线程安全的追踪工具类:

using System.Runtime.InteropServices;
using System.Threading;
using System.Collections.Concurrent;

public static class UnmanagedAllocatorTracker
{
    private static long _totalAllocatedBytes = 0;
    private static readonly ConcurrentDictionary<IntPtr, int> _allocationMap = new();

    public static IntPtr AllocHGlobal(int cb)
    {
        var ptr = Marshal.AllocHGlobal(cb);
        _allocationMap.TryAdd(ptr, cb);
        Interlocked.Add(ref _totalAllocatedBytes, cb);
        return ptr;
    }

    public static void FreeHGlobal(IntPtr ptr)
    {
        if (_allocationMap.TryRemove(ptr, out int allocatedSize))
        {
            Interlocked.Add(ref _totalAllocatedBytes, -allocatedSize);
        }
        Marshal.FreeHGlobal(ptr);
    }

    public static long GetTotalAllocatedBytes()
    {
        return Interlocked.Read(ref _totalAllocatedBytes);
    }
}

该类通过维护分配映射表,能精确统计Marshal.AllocHGlobal系列调用的总分配内存,适合作为自定义追踪指标。

二、外部CLI工具获取

1. dotnet-counters(官方推荐,实时监控)

这是.NET官方轻量级性能监控工具,无需调试环境,可实时获取内存指标:

  • 安装:dotnet tool install --global dotnet-counters
  • 运行:找到目标进程PID后执行:
    dotnet counters monitor --process-id <目标进程PID> System.Runtime
    
    重点关注输出中的两个字段:
    • Private Bytes:进程私有内存总量
    • Heap Size:托管堆已使用内存
      两者差值即为非托管内存总量;若需更细粒度数据,可添加对应业务组件的计数器组(如Microsoft.AspNetCore.Hosting)。

2. 系统原生工具

  • Windows:用tasklist查看进程内存:
    tasklist /fi "PID eq <PID>" /v /fo list
    
    结合dotnet-counters的托管堆数据,可计算非托管内存总量。
  • Linux/macOS:用ps命令查看内存:
    ps -o rss,vsize -p <PID>
    
    vsize为虚拟内存总量,rss为驻留集大小,搭配托管堆数据可估算非托管内存。

内容的提问来源于stack exchange,提问作者andresp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 15:37:54