DotMemory系列:5. 如何实现自动化抓取和应用自托管

一:背景

1. 讲故事

前面几篇我们都是手工安装 dotmemory 软件,然后在程序的合适时机抓取snapshot,这种方式在绝大多数场景下都没有问题,但在一些精细化的场景下,如果能够实现自动化抓取,那就比较🐂👃了,这篇我们就来聊一聊这玩意。

二:如何实现自动化抓取

1. 测试代码

所谓的自动化抓取,意思就是用代码来控制 snapshot 的抓取时机,而不是你在 UI 上点来点去,为了方便测试,先上一段测试代码,参考如下:

复制代码
    internal class Program
    {
        static void Main()
        {
            var analyzer = new MemoryAnalyzer();
            analyzer.ProcessData();

            Console.ReadLine();
        }
    }

    public class MemoryAnalyzer
    {
        private readonly List<string> _data = new();

        public void ProcessData()
        {
            // 模拟内存密集型操作
            for (int i = 0; i < 10000; i++)
            {
                _data.Add(new string('x', 1000));
            }

            Console.WriteLine("数据处理完成,3秒后生成快照...");
            Thread.Sleep(3000);

            MemoryProfiler.GetSnapshot("ProcessDataSnapshot");
            Console.WriteLine("快照已生成");
        }
    }

上面的代码非常简单,我想在 ProcessData() 方法内的某一个时点通过MemoryProfiler.GetSnapshot 方法自动化抓取snapshot,这个让你在UI上点击,你根本无法做到。

2. dotmemory 集成交互

代码里埋好点之后,接下来打开 dotmemory,使用 Using API 模式,这样就相当于给程序开了一个口子,截图如下:

接下来点击 Start 按钮,可以看到程序自动的帮我们生成了一个叫 ProcessDataSnapshot 的snapshot,是不是挺有意思的,截图如下:

三:如何实现自托管

1. 测试代码

所谓的自托管就是让代码自己去下载 Console of DotMemory,全程不需要人为干预,最终会产生一个后缀为 *.dmw 的跟踪文件,参考代码如下:

复制代码
    internal class Program
    {
        static void Main(string[] args)
        {
            DotMemory.Init();
            var config = new DotMemory.Config();
            config.SaveToDir(@"E:\testdump");

            DotMemory.Attach(config);

            Console.WriteLine("=== 内存分析开始 ===\n");

            var memoryDemo = new MemoryDemo();

            DotMemory.GetSnapshot("Initial");
            Console.WriteLine("初始快照已生成");

            memoryDemo.CreateObjects();
            DotMemory.GetSnapshot("AfterCreation");
            Console.WriteLine("对象创建后快照已生成");

            memoryDemo.Cleanup();
            DotMemory.GetSnapshot("AfterCleanup");
            Console.WriteLine("清理后快照已生成");

            Console.WriteLine("\n=== 分析完成 ===");

            DotMemory.Detach();
        }
    }

    public class MemoryDemo
    {
        private List<string> _strings = new();
        private List<byte[]> _buffers = new();
        private List<char[]> _charArrays = new();

        public void CreateObjects()
        {
            Console.WriteLine("创建对象中...");

            for (int i = 0; i < 500000; i++)
            {
                _strings.Add($"Data_{i}_{Guid.NewGuid()}_AdditionalPaddingDataToMakeStringLarger");
            }

            for (int i = 0; i < 5000; i++)
            {
                _buffers.Add(new byte[1024 * 200]);
            }

            for (int i = 0; i < 100; i++)
            {
                _buffers.Add(new byte[1024 * 1024 * 5]);
            }

            for (int i = 0; i < 10000; i++)
            {
                _charArrays.Add(new char[1024 * 50]);
            }

            Console.WriteLine($"已创建: {_strings.Count} 个字符串, {_buffers.Count} 个缓冲区, {_charArrays.Count} 个字符数组");
        }

        public void Cleanup()
        {
            Console.WriteLine("清理对象中...");

            _strings.Clear();
            _buffers.Clear();
            _charArrays.Clear();

            GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
            GC.Collect(2, GCCollectionMode.Forced, true, true);
            GC.WaitForPendingFinalizers();

            Console.WriteLine("清理完成");
        }
    }

上面的代码会在程序运行的三个阶段抓取snapshot,将程序运行起来之后,从下图可以清晰的看到已生成三个 snapshot 快照,是不是挺有意思,截图如下:

2. Console 版 DotMemory 分析

自托管借助的是 Console 版 DotMemory,不要小看这个 Console,它可以跨平台,也可以集成到各种 自动化发布工具 里面去,这里我就简单演示下在 ubuntu 上如何用 console 版抓 .net 程序的 snapshot 到 windows 上分析。

首先到 https://www.jetbrains.com/dotmemory/download/?section=commandline 上下载安装包,截图如下:

复制代码
root@ubuntu2404:/data# tar -xzvf JetBrains.dotMemory.Console.linux-x64.2025.3.0.1.tar.gz

root@ubuntu2404:/data# ps -ef | grep dotnet
root        3007    2962  0 12:13 pts/1    00:00:00 dotnet Example_6_6.dll
root        3018    1938  0 12:13 pts/0    00:00:00 grep --color=auto dotnet
root@ubuntu2404:/data# ./dotMemory.sh get-snapshot 3007 --save-to-dir=./         
dotMemory.sh is deprecated and will soon be removed: Use the dotmemory command instead.
Performs memory profiling of .NET applications

Found 1 process(es):
  [3007] dotnet

Attaching to [3007] dotnet runtime...
Profiler connected. PID:3007, Core CLR runtime v8.0.15.0
  ATTACHED. Getting snapshot...
  [PID:3007] Saving snapshot... ~5.6 K objects
  [PID:3007] SNAPSHOT #1 SAVED.
  [PID:3007] Processing snapshot #1...
  [PID:3007] SNAPSHOT #1 READY.
Profiler disconnected. PID:3007

Saving workspace...
WORKSPACE SAVED
file:///data/[3007]-dotnet.2025-11-17T12-14-10.141.dmw

从上面的输出可以看到 dmw 文件已生成,接下来将文件导入到 windows 平台上,双击打开。

相关推荐
AOwhisky11 分钟前
Linux(CentOS)系统管理入门笔记(第二十一期)——防火墙管理(Firewalld)——zone、服务端口、富规则与端口转发
linux·运维·笔记·安全·centos·防火墙
腾飞开源24 分钟前
01_K8s干货笔记之认识K8s
运维·笔记·云原生·容器·kubernetes·k8s·容器化部署
布鲁飞丝7 小时前
vivo Pulsar 万亿级消息处理实践()-Ansible运维部署
运维·ansible
XR1234567887 小时前
企业全光网络架构选型技术白皮书:从物理层到运维层的全链路分析
运维·网络·架构
IT小白杨8 小时前
从环境制备到自动化工作流:多账号运营的工程化架构拆解
java·经验分享·自动化·安全架构·指纹浏览器
HiDev_8 小时前
【非标自动化】2、认识元器件(直线模组)
运维·自动化
浦信仿真大讲堂8 小时前
从重复操作到自动化闭环:如何让 CST 与 Python 真正协同起来
python·自动化·cst·仿真软件·达索软件
龙仔7258 小时前
人大金仓 KingbaseES V8 只读账号创建完整运维笔记
运维·笔记·sql·人大金仓
凯丨9 小时前
AI 蠕虫来了:恶意文档如何通过 Copilot for Word 自我传播?
人工智能·c#·copilot
我不管我就要叫小猪9 小时前
嵌入式Linux----网络通信
linux·运维·服务器