首页 > 解决方案 > 计数(非垃圾收集)对象的方式

问题描述

我在生产应用程序中有内存泄漏。该应用程序将运行良好,然后突然内存将急剧下降。由于我无法控制的原因,我无法附加普通的内存分析器(如 dotMemory)。

有什么方法可以从我的应用程序代码中定期计算当前存在于应用程序中的对象的数量?

标签: c#debuggingmemory-leaksgarbage-collectionprofiling

解决方案


该问题无法用笼统的答案来回答,但是,您可以尝试以下方法之一:

  • 暂停/冻结您的应用程序并创建进程的内存转储(假设您使用的是 Windows,您可以使用任务管理器的详细信息窗格并右键单击任何进程并使用命令Create dump file
    然后您可以使用 Visual Studio 打开转储文件,它可以自动重新创建内存堆。

  • 使用 Visual Studio 自己的内存分析器。它可以检查所有堆对象、它们的大小、计数、类型等。有关更多信息,请参阅https://docs.microsoft.com/en-us/visualstudio/profiling/memory-usage?view=vs-2022

  • 使用外部分析工具没关系,你说那是不可能的

  • 实现您自己的对象计数器(假设您正在计算自己的对象):

    // a dataset of all object informations you want to store
    public record ObjectInfo(
        DateTime DateTimeAllocated,
        Type Type,
        ...
    )
    
    public abstract class profilable_object
        : object
    {
        public static readonly ConcurrentDictionary<profilable_object, ObjectInfo> Heap = new();
    
    
        public profilable_object() =>
            Heap[this] = new(DateTime.Now, GetType(), ...);
    
        ~profilable_object() => Heap.TryRemove(this, out _);
    }
    

    然后让你所有的类都继承自profilable_object. 然后,您可以使用静态字段检查您的“堆” profilable_object.Heap
    查看GitHub 项目“sharplab.io”中的这个文件,了解如何获取堆对象的大小和布局。

    不用说,这种解决方案会严重影响性能,只能作为最后的手段使用。


推荐阅读