如何获得未使用的内存从多个管理应用程序的大型对象堆LOH回来? [英] How to get unused memory back from the large object heap LOH from multiple managed apps?

查看:172
本文介绍了如何获得未使用的内存从多个管理应用程序的大型对象堆LOH回来?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在谈论一个关于使用上启动了近1.5G内存的应用程序的特定组的同事......他指着我上的。NET生产调试

这有我困惑的部分是...

  

例如,如果您分配1 MB的   内存单块,大的   对象堆扩展到1 MB的大小。   当你这个对象,大   对象堆不decommit的   虚拟内存,所以堆保持在1   MB的大小。如果您分配另一个   500-KB块后,新块   的1 MB块内分配   属于大对象存储   堆。在这个过程中生命周期中,   大对象堆总是长举行   所有大的块分配   目前引用的,但从来没有   收缩对象时被释放,   即使垃圾收集发生。   图2.4的下一个页面上显示了   比如一个大对象堆。

现在假设我们有一个虚构的应用程序,创建大对象(> 85KB)乱舞,所以大对象堆的增长可以说200梅格。现在,假设我们已经运行10个这样的应用程序实例。所以,在2000年梅格斯分配。现在是该内存永远不会还给操作系统,直到进程关闭......(我是这么理解的)

有没有在我的理解上的差距?我们如何取回未使用的内存在的各种LOHeaps;我们没有创造出完美风暴OutOfMemoryExceptions的?

更新:从马克的回应,我想澄清一点,陆恭蕙对象没有被引用 - 大对象是使用正掷 - 但是堆不收缩,即使堆比较空后的初始冲击。

更新#2:只是包括code段(夸张,但得到的点对面,我认为)。我看到周围的虚拟内存击中了1.5G标记时一个OutOfMemoryException我的机器(1.7G上的另一个)。从<一个href="http://blogs.msdn.com/ericlippert/archive/2009/06/08/out-of-memory-does-not-refer-to-physical-memory.aspx"相对=nofollow>埃里克L.的博客文章,进程的内存可以看作磁盘上的一个巨大的文件...... - 这样的结果就是这样出乎意料。在这种情况下,机器具有在HDD自由空间绿带。请问pagefile.sys的操作系统文件(或相关设置)施加任何限制吗?

 静浮_megaBytes;
        静态只读INT BYTES_IN_MB = 1024 * 1024;

        静态无效BigBite()
        {
           尝试
           {
              VAR名单=新的名单,其中,byte []的&GT;();
              INT I = 1;

              对于(INT X = 0,X&LT; 1500,X ++)
              {
                 VAR内存=新的字节[BYTES_IN_MB + 1];
                 _megaBytes + = memory.Length / BYTES_IN_MB;
                 list.Add(内存);
                 Console.WriteLine(分配#{0}:{1} MB现在,我++,_megaBytes);
              }
           }
           赶上(例外五)
           {Console.WriteLine(轰{0}!,E); //我把一个断点这里检查控制台
              扔;
           }
        }
       静态无效的主要(字串[] args)
        {
            BigBite();
            Console.WriteLine(检查虚拟机吧!);到Console.ReadLine();
            _megaBytes = 0;

            ThreadPool.QueueUserWorkItem(委托{BigBite();});
            ThreadPool.QueueUserWorkItem(委托{BigBite();});
            到Console.ReadLine(); //之前到达这里会吹
        }
 

解决方案

有一个澄清,我想先作。 - 假设你正在运行的应用程序作为一个32位的应用程序,弗吉尼亚州可用空间为您的过程只有2 GB,如果你启用了大的地址空间3GB开关,所以即使你有巨大的页面文件,它不会,如果你是32位无所谓过程中,它很重要,如果你运行64位,在这里你有巨大的地址空间。

  • 在大小为对象> 85000字节分配上蕙,值得注意的是 85000字节不85K,这也是实现细节可能会改变。 现在,回到你的问题。 GC将未提交未在2的情况下使用的LOH段 1当机器上的内存pressure高(〜95-98%) 2 - 当它无法满足新的分配请求,它会decommit在LOH
  • 未使用的网页

所以你会找回记忆中的这些案件之一。 那你打的OOM达到2GB的限制之前,这一事实可能意味着你有VA碎片,当你不具备连续VA的地址空间来满足新的分配你不要VA碎片发生的,比如你问8KB段,并且吨有连续2页的VA(假设页面大小为4 K)

您可以使用!vamap调试器扩展在Windows调试工具来验证这一点。

希望这有助于 谢谢

While talking to a colleague about a particular group of apps using up nearly 1.5G memory on startup... he pointed me to a very good link on .NET production debugging

The part that has me puzzled is ...

For example, if you allocate 1 MB of memory to a single block, the large object heap expands to 1 MB in size. When you free this object, the large object heap does not decommit the virtual memory, so the heap stays at 1 MB in size. If you allocate another 500-KB block later, the new block is allocated within the 1 MB block of memory belonging to the large object heap. During the process lifetime, the large object heap always grows to hold all the large block allocations currently referenced, but never shrinks when objects are released, even if a garbage collection occurs. Figure 2.4 on the next page shows an example of a large object heap.

Now let's say we have a fictional app that creates a flurry of large objects ( > 85KB), so the large object heap grows lets say to 200 Meg. Now lets say we have 10 such app instances running.. so that 2000 Megs allocated. Now is this memory never given back to the OS until the process shuts down... (is what I understood)

Are there any gaps in my understanding? How do we get back unused memory in the various LOHeaps ; we don't create the perfect storm of OutOfMemoryExceptions ?

Update: From Marc's response, I wanted to clarify that the LOH objects are not referenced - the large objects are use-n-throw - however the heap doesn't shrink even though the heap is relatively empty post the initial surge.

Update#2: Just including a code snippet (exaggerated but gets the point across I think).. I see an OutOfMemoryException around the time the Virtual memory hits the 1.5G mark on my machine (1.7G on another).. From Eric L.'s blog post, 'process memory can be visualized as a massive file on disk..' - this result is thus unexpected. The machines in this instance had GBs of free space on the HDD. Does the PageFile.sys OS file (or related settings) impose any restrictions?

        static float _megaBytes;
        static readonly int BYTES_IN_MB = 1024*1024;

        static void BigBite()
        {
           try
           {
              var list = new List<byte[]>();
              int i = 1;

              for (int x = 0; x < 1500; x++)
              {
                 var memory = new byte[BYTES_IN_MB + i];
                 _megaBytes += memory.Length / BYTES_IN_MB;
                 list.Add(memory);
                 Console.WriteLine("Allocation #{0} : {1}MB now", i++, _megaBytes);
              }
           }
           catch (Exception e)
           {  Console.WriteLine("Boom! {0}", e); // I put a breakpoint here to check the console
              throw;
           }
        }
       static void Main(string[] args)
        {
            BigBite();
            Console.WriteLine("Check VM now!"); Console.ReadLine();
            _megaBytes = 0;

            ThreadPool.QueueUserWorkItem(delegate { BigBite(); });
            ThreadPool.QueueUserWorkItem(delegate { BigBite(); });
            Console.ReadLine();   // will blow before it reaches here
        }

解决方案

There is a clarification I would like to make first. - Assuming you are running app as a 32bit app, the VA space available for your process is only 2 GB , 3GB if you enabled large address space switch, so even if you have HUGE page file, it doesn't matter if you are 32bit process, it matters if you run 64bit, where you have huge address space.

  • Object with size > 85000 bytes are allocated on LOH, note it is 85000 bytes not 85K, it is also implementation details that could change. Now, back to your question. The GC will un-commit the LOH segments that are not used in 2 situations 1- When the memory pressure on the machine is high ( ~95-98% ) 2- When it fails to satisfy new allocation requests, it will decommit the unused pages in the LOH

so you will get back the memory in one of these cases. The fact that you are hitting an OOM before reaching the 2GB limit could mean you have VA fragmentation, VA fragmentation occur when you don't have continuous VA address space to satisfy new allocation, for example you ask for 8KB segment, and you don't have 2 consecutive pages in your VA ( assuming page size is 4 K)

you can use !vamap debugger extension in Debugging tools for windows to validate this.

Hope this helps Thanks

这篇关于如何获得未使用的内存从多个管理应用程序的大型对象堆LOH回来?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆