ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

从32位进程切换到64位进程后,CLR /高内存消耗

2019-11-21 12:09:00  阅读:320  来源: 互联网

标签:memory memory-leaks clr memory-management c


我有一个基于.NET Framework 4.5(C#)构建的后端应用程序(Windows服务).该应用程序在具有64GB内存的Windows Server 2008 R2服务器上运行.

由于我的依赖关系,我曾经以32位进程的形式编译和运行此应用程序(将其编译为x86),并使用/ LARGEADDRESSAWARE标志使该应用程序在用户空间中使用超过2GB的内存.使用此配置,平均内存消耗(根据任务管理器中的“内存(私有工作集)”列)约为300-400MB.

我需要LARGEADDRESSAWARE标志的原因,以及将其更改为64位的原因是,尽管平均为300-400MB,但此应用偶尔执行的工作涉及将大量数据加载到内存中(并且当您在内存方面不是很有限时,开发和管理这类东西就容易得多了.

最近(除去那些x86本机依赖项之后),我将应用程序编译更改为“ Any CPU”,因此,现在,在生产服务器上,它作为64位进程运行.从我进行此更改开始,平均内存消耗(根据任务管理器)达到了新的水平:3-4 GB,此时没有其他更改可以解释此行为更改.

以下是有关当前状态的其他一些事实:

>根据“所有堆中的#Bytes”计数器,内存总量约为600MB.
>使用WinDbg SOS调试进程时,!dumpheap -stat显示大约有250-300MB的可用空间,但是所有其他对象都小于该进程使用的内存总量.
>根据GC性能指标,有定期的Gen0集合.实际上,“%GC时间”计数器表示平均花费在GC上的时间为10-20%(考虑到应用程序的性质,这很有意义-大量用于信息和数据结构的分配短时间).
>我在此应用中使用Server GC.
>服务器上没有内存问题.它使用约50-60%的可用内存(64GB).

我的问题:

>为什么分配给进程的内存(根据任务管理器)与CLR堆的实际大小(在进程中没有非托管代码可以解释这一点)之间有很大的区别?
>为什么与32位进程运行的同一个进程相比,64位进程占用更多的内存?即使考虑到指针的大小是其两倍,也存在很大差异.
>我可以做些降低内存消耗或更好地了解此问题的事情吗?

谢谢!

解决方法:

有几件事情要考虑:

1)您提到您正在使用服务器GC模式.在服务器GC模式下,CLR为计算机上的每个CPU内核创建一个堆,这在服务器进程中更高效,更多线程地进行处理,例如Asp.Net进程.每个堆都有两个段:一个用于小对象,一个用于大对象.每个段以4 gb的保留内存开始.基本上,服务器GC模式会尝试使用系统上更多的内存来换取整体系统性能.

2)当然,在64位上,指针更大.

3)由于堆大得多,因此在服务器GC模式下,前景Gen2 GC变得非常昂贵.因此,CLR有时会尝试使用后台Gen2 GC来尽力减少前台Gen2 GC的数量.

4)根据使用情况,碎片化可能成为一个现实问题.我见过堆有98%的碎片(98%的堆是空闲块).

要真正解决您的问题,您需要获取一个ETW跟踪内存转储,然后使用PerfView之类的工具进行详细分析.

标签:memory,memory-leaks,clr,memory-management,c
来源: https://codeday.me/bug/20191121/2051702.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有