C#中的每线程内存管理

时间:2010-05-26 13:45:20

标签: c# memory-management parallel-processing contention

继续Understanding VS2010 C# parallel profiling results的讨论,但更重要的是:

我有很多并行工作的线程(使用Parallel.For / Each),它们为小类使用了很多内存分配。

这会在全局内存分配器线程上产生争用。

有没有办法指示.NET为每个线程预分配内存池并从该池中进行所有分配?

目前我的解决方案是我自己的内存池实现(全局分配的类型为T的对象数组,在线程中循环使用),这有很大帮助,但效率不高,因为:

  1. 我不能指示.NET从特定的内存片中分配。
  2. 我仍然需要多次调用 new 来为池分配内存。
  3. 谢谢,

3 个答案:

答案 0 :(得分:16)

我搜索了两天试图找到你遇到的同一个问题的答案。答案是您需要将垃圾收集模式设置为服务器模式。默认情况下,垃圾收集模式设置为Workstation模式。 将垃圾收集设置为服务器模式会导致托管堆拆分为单独管理的部分,每个CPU一个。 为此,您需要在app.config文件中添加配置设置。

<runtime>
   <gcServer enabled="true"/>
</runtime>

我的12核Opteron 6172的速度差异非常大!

答案 1 :(得分:0)

垃圾收集器不分配内存。

这听起来更像是在分配大量的小型临时对象和一些长期存在的对象,而垃圾收集器花费大量时间来垃圾收集临时对象,因此您的应用程序无需请求更多来自操作系统的内存。来自.NET Framework 4 Advanced Development - Garbage Collection

  

只要托管堆中的地址空间可用,运行时就会继续为新对象分配空间。但是,记忆并不是无限的。最终垃圾收集器必须执行一个集合才能释放一些内存。

解决方案:不要分配大量小型临时对象。 Garbage Collection and Performance上的页面也可能会有所帮助。

答案 2 :(得分:0)

您可以预先分配一堆对象,并将它们保存在用于单独线程的组中。但是,你可能不会从中获得更好的表现。

垃圾收集器专门用于有效处理小型短寿命对象。如果将对象保留在池中,它们将是长期存在的并且将在垃圾收集中存活,这反过来意味着它们将被复制到第二代堆。这种复制比分配新对象更昂贵。