[C#] 减少.NET应用程序的内存使用情况?


Answers

由于.NET应用程序必须在进程中加载​​运行时和应用程序,因此与本地应用程序相比,.NET应用程序的占用空间更大。 如果你想要的东西真的很整洁,.NET可能不是最好的选择。

但是,请记住,如果您的应用程序大多处于睡眠状态,则必要的内存页面将被换出内存,因此在大多数情况下,系统上的负担并不那么大。

如果你想保持足迹小,你将不得不考虑内存使用情况。 这里有几个想法:

  • 减少对象的数量,并确保不要超过需要的时间。
  • 请注意List<T>以及类似的类型,因为它们可能会导致50%的浪费,所以需要时将容量翻倍。
  • 你可以考虑在引用类型上使用值类型来强制堆栈中的内存更多,但请记住,默认堆栈空间仅为1 MB。
  • 避免超过85000字节的对象,因为它们将进入不被压缩的LOH,因此可能容易被分割。

这可能不是一个详尽无遗的清单,而只是一些想法。

Question

有什么提示可以减少.NET应用程序的内存使用量? 考虑以下简单的C#程序。

class Program
{
    static void Main(string[] args)
    {
        Console.ReadLine();
    }
}

x64的 发行模式下编译并在Visual Studio外运行,任务管理器报告以下内容:

Working Set:          9364k
Private Working Set:  2500k
Commit Size:         17480k

如果仅针对x86进行编译,则会更好一些:

Working Set:          5888k
Private Working Set:  1280k
Commit Size:          7012k

然后我尝试了下面的程序,它执行相同的操作,但是尝试在运行时初始化后修剪进程大小:

class Program
{
    static void Main(string[] args)
    {
        minimizeMemory();
        Console.ReadLine();
    }

    private static void minimizeMemory()
    {
        GC.Collect(GC.MaxGeneration);
        GC.WaitForPendingFinalizers();
        SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle,
            (UIntPtr) 0xFFFFFFFF, (UIntPtr)0xFFFFFFFF);
    }

    [DllImport("kernel32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool SetProcessWorkingSetSize(IntPtr process,
        UIntPtr minimumWorkingSetSize, UIntPtr maximumWorkingSetSize);
}

在Visual Studio之外的x86 版本上的结果:

Working Set:          2300k
Private Working Set:   964k
Commit Size:          8408k

哪个更好一点,但对于这样一个简单的程序来说似乎仍然过分。 是否有任何技巧可以使C#过程变得更加精简? 我正在编写一个旨在大部分时间在后台运行的程序。 我已经在独立的应用程序域中执行了任何用户界面工作,这意味着用户界面的内容可以安全地卸载,但当它坐在后台时占用10 MB似乎过多。

PS至于为什么我会关心---(电源)用户往往担心这些事情。 即使它对性能几乎没有影响,半精通技术的用户(我的目标受众)往往会陷入后台应用程序内存使用的窘境。 甚至当我看到Adobe Updater获得11 MB内存并且感受到Foobar2000的平静触感时,即使在播放时也可能需要6 MB以下的抚慰,我仍然感到非常惊讶。 我知道在现代操作系统中,这些东西在技术上确实无关紧要,但这并不意味着它对感知没有影响。




解决标题中的一般问题而不是具体问题:

如果你正在使用一个返回大量数据的COM组件(比如说大的2xN数组),并且只需要一小部分,那么可以编写一个包装器COM组件,该组件将隐藏.NET中的内存并仅返回数据需要。

这就是我在我的主应用程序中所做的,它显着改善了内存消耗。




还有一些方法可以减少这个简单程序的私人工作集:

  1. NGEN你的申请。 这将从您的流程中移除JIT编译成本。

  2. 使用MPGO训练您的应用程序, 减少内存使用量 ,然后使用 NGEN。




本身没有具体的建议,但您可以查看CLR Profiler (从Microsoft免费下载)。
安装完成后,请查看此操作指南页面

从如何操作:

本教程向您展示了如何使用CLR Profiler工具来调查应用程序的内存分配配置文件。 您可以使用CLR Profiler来识别导致内存问题的代码,例如内存泄漏和垃圾收集过多或效率低下。