大arrays和LOH碎片。 什么是公认的惯例?
关于一些可能涉及LOH碎片的可能还有其他未知因素的无望记忆问题,我在这里还有另一个活跃的问题。
我现在的问题是,接受的做事方式是什么? 如果我的应用程序需要在Visual C#中完成,并且需要处理大型数组到int [4000000]的调整,我怎么能不注意垃圾收集器拒绝处理LOH?
似乎我被迫将任何大型数组全局化,并且从不在它们周围使用“new”这个词。 所以,我留下了带有“maxindex”变量的不合适的全局数组,而不是由函数传递的整齐大小的数组。
我总是被告知这是不好的做法。 还有什么选择?
System.GC.CollectLOH("Seriously")
是否有某种function? 是否有可能将垃圾收集外包给System.GC以外的其他方式?
无论如何,处理大型(> 85Kb)变量的普遍接受的规则是什么?
首先,垃圾收集器确实收集了LOH,因此不要立即被它的早期吓到。 收集第2代时收集LOH。
不同之处在于LOH不会被压缩,这意味着如果你有一个具有较长寿命的物体,那么你将有效地将LOH分成两个部分 – 前面的区域和该物体之后的区域。 如果这种情况继续发生,那么你最终可能会遇到这样的情况,即长期存在的对象之间的空间不足以进行后续分配,并且.NET必须分配越来越多的内存才能放置大对象,即LOH变得支离破碎。
现在,话虽如此,如果LOH的末端区域完全没有活物,那么LOH的大小会缩小,所以唯一的问题是如果你将物体留在那里很长时间(例如应用的持续时间)。
避免LOH分裂的策略是:
编辑:双arrays的LOH阈值似乎是8k。
这是一个老问题,但我认为用.NET中引入的更改来更新答案并没有什么坏处。 现在可以对大对象堆进行碎片整理。 显然,首选应该是确保做出最佳设计选择,但现在有了这个选项很好。
https://msdn.microsoft.com/en-us/library/xe0c2357(v=vs.110).aspx
“从.NET Framework 4.5.1开始,您可以通过在调用Collect方法之前将GCSettings.LargeObjectHeapCompactionMode属性设置为GCLargeObjectHeapCompactionMode.CompactOnce来压缩大对象堆(LOH),如以下示例所示。”
可以在System.Runtime命名空间中找到GCSettings
GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce; GC.Collect();
首先要想到的是将arrays分成较小的arrays,这样它们就无法到达GC所需的内存来放入LOH。 你可以将数组吐成10,000个较小的数组,然后构建一个对象,根据你传递的索引器知道要查找哪个数组。
现在我还没有看到代码,但我也会质疑为什么你需要一个大的数组。 我可能会考虑重构代码,因此所有这些信息不需要立即存储在内存中。
你弄错了。 你不需要有4000000的数组大小,你绝对不需要调用garbace收集器。
这允许您仅使用一个重定向访问基本上所有元素。 并且,由于单个arrays较小,碎片不是问题…
……如果是……那么REUSE页面。 不要把它们扔掉处理掉,把它们放在一个静态的“PageList”上并先从那里拉出来。 所有这些都可以在你的课堂上透明地完成。
真正的好处是这个List在内存使用方面非常动态。 您可能想要调整holder数组(重定向器)的大小。 即使不是,也只是每页约512kbdata。
二级数组每个字节基本上有64k – 一个类是8字节(每页512kb,32位256kb),或每个结构字节64kb。
技术上:
将int []转换为int [] []
根据需要确定32位或64位是否更好;)两者都有优点和缺点。
在任何语言中处理一个大型arrays都是不可能的 – 如果你愿意,那么……基本上……在程序启动时分配,永远不会重新创建。 只有解决方案
在问题如何产生方面,我在上面的答案中加以阐述。 LOH的碎片不仅取决于长期存在的对象,而且如果你有多个线程并且每个都创建大型列表进入LOH的情况,那么你可能会遇到第一个线程的情况需要增加它的List但是下一个连续的内存位已经被第二个线程的List占用,因此运行时将为第一个线程List分配新的内存 – 留下一个相当大的漏洞。 这是目前在我inheritance的一个项目中发生的事情,因此即使LOH大约为4.5 MB,运行时总共有117 MB的可用内存,但最大的可用内存段是28MB。
没有多个线程可能会发生这种情况的另一种方法是,如果在某种循环中添加了多个列表,并且每个列表都扩展到最初分配给它的内存之外,那么当它们超出分配的空间时,每个都会超越另一个。
一个有用的链接是: https : //www.simple-talk.com/dotnet/.net-framework/the-dangers-of-the-large-object-heap/
仍在为此寻找解决方案,一种选择可能是使用某种池化对象并在进行工作时从池中请求。 如果你正在处理大型数组,那么另一个选择就是开发一个自定义集合,例如集合集合,这样你就不会只有一个巨大的列表,而是将它分解成更小的列表,每个列表都避免使用LOH。
上述就是C#学习教程:大arrays和LOH碎片。 什么是公认的惯例?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1043458.html