减少.NET应用程序的内存使用量?

Rob*_*ser 107 .net c# memory optimization memory-optimization

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

class Program
{
    static void Main(string[] args)
    {
        Console.ReadLine();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Working Set:          9364k
Private Working Set:  2500k
Commit Size:         17480k
Run Code Online (Sandbox Code Playgroud)

如果它只为x86编译它会好一点:

Working Set:          5888k
Private Working Set:  1280k
Commit Size:          7012k
Run Code Online (Sandbox Code Playgroud)

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

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);
}
Run Code Online (Sandbox Code Playgroud)

在Visual Studio外部的x86 发布上的结果:

Working Set:          2300k
Private Working Set:   964k
Commit Size:          8408k
Run Code Online (Sandbox Code Playgroud)

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

PS至于为什么我会关心---(Power)用户往往担心这些事情.即使它对性能几乎没有影响,半精通技术的用户(我的目标受众)倾向于对背景应用程序内存使用情况进行调整.当我看到Adobe Updater占用11 MB的内存并且感受到Foobar2000的平静触摸时,即使我玩的时候也可以拿到6 MB以下,我甚至会感到蠢蠢欲动.我知道在现代操作系统中,这些东西在技术上并不重要,但这并不意味着它对感知没有影响.

Bri*_*sen 44

与本机应用程序相比,.NET应用程序占用的空间更大,因为它们都必须在流程中加载运行时和应用程序.如果你想要一些非常整洁的东西,.NET可能不是最好的选择.

但是,请记住,如果您的应用程序主要处于休眠状态,那么必要的内存页面将被换出内存,因此在大多数情况下不会对系统造成太大的负担.

如果您想要缩小占用空间,则必须考虑内存使用情况.以下是一些想法:

  • 减少对象的数量,并确保不要持有超过所需的任何实例.
  • 请注意List<T>并在需要时将容量增加一倍,因为它们可能导致50%的浪费.
  • 您可以考虑在引用类型上使用值类型来强制堆栈上有更多内存,但请记住,默认堆栈空间只有1 MB.
  • 避免超过85000字节的对象,因为它们将转到未压缩的LOH,因此可能很容易碎片化.

无论如何,这可能不是一个详尽的清单,而只是一些想法.


Joh*_*udy 33

  1. 您可能想查看Stack Overflow问题.NET EXE内存占用.
  2. MSDN博客文章工作集!=实际内存占用量就是揭开工作集,进程内存以及如何对总内存消耗进行精确计算.

我不会说你应该忽略你的应用程序的内存占用 - 显然,更小,更高效往往是可取的.但是,您应该考虑您的实际需求.

如果您正在编写一个标准的Windows窗体和WPF客户端应用程序,这些应用程序注定要在个人的PC上运行,并且很可能是用户操作的主要应用程序,那么您可以通过更加缺乏内存分配来实现.(只要这一切都被解除分配.)

但是,为了解决这里不想担心的人:如果你正在编写一个将在终端服务环境中运行的Windows窗体应用程序,在可能由10个,20个或更多用户使用的共享服务器上,那么是,你绝对必须考虑内存使用情况.你需要保持警惕.解决这个问题的最佳方法是使用良好的数据结构设计,并遵循有关何时以及分配的最佳实践.


Jar*_*Par 16

在这种情况下,您需要考虑的一件事是CLR的内存成本.每个.Net进程都会加载CLR,因此会考虑内存因素.对于这样一个简单/小程序,CLR的成本将主导您的内存占用.

构建一个真实的应用程序并查看与该基准程序的成本相比的成本将更具指导性.


Don*_*nut 7

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

从方法到:

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


Eri*_*lje 6

可能想看看"真实"应用程序的内存使用情况.

与Java类似,无论程序大小如何,运行时都会有一些固定的开销,但在此之后内存消耗将更加合理.


Fen*_*uan 6

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

  1. NGEN 您的申请。这可以消除流程中的 JIT 编译成本。

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