我正在创建一个桌面应用程序,其中有一个计算密集型操作,可能需要运行几秒钟。显然需要尽量缩短此操作的时间。该操作很容易并行化(单个子任务),每个子任务在单个线程上需要约50ms。在多个线程上,每个子任务需要4-5倍的时间,因为40-50%的时间花费在GC上,实际上完全取消了速度提升。
因此,我需要让GC工作更少。我的第一个想法是尝试找出哪种类型的对象被垃圾回收最多,但我意识到,尽管我经常进行内存分析,但我从未搜索过这样的模式。通常查看堆快照或堆快照之间的差异,但这些显示的是活动对象,而不是在这些快照之间创建和处理的对象。因此,这是我的第一个问题:找到创建和垃圾回收最多的类型的最简单方法是什么?我尝试查找方法调用计数,以查看是否调用了某个构造函数,但是创建数百万个对象的所有对象都只是小的结构体类型。如果我理解正确,即使装箱,这些也不应对GC产生影响?
该算法创建了数十万个单独的结果点对象。当然,这些对象不应该被垃圾回收,因为它们代表操作的输出。但这引出了我的第二个问题:GC所花费的时间主要是取决于总对象数量还是实际收集的对象数量?我应该尝试限制结果对象的数量,而使用更少但更大的结果对象吗?
编辑:我使用VS 2010并发可视化器找到了在GC中所花费的时间。此外,在并行代码中,大多数阻塞线程的部分都在等待GC。
编辑:我应该澄清一下,性能问题是因为执行在工作站GC上实际上是串行化的。例如,参见此帖子中描述的性能问题。
因此,我需要让GC工作更少。我的第一个想法是尝试找出哪种类型的对象被垃圾回收最多,但我意识到,尽管我经常进行内存分析,但我从未搜索过这样的模式。通常查看堆快照或堆快照之间的差异,但这些显示的是活动对象,而不是在这些快照之间创建和处理的对象。因此,这是我的第一个问题:找到创建和垃圾回收最多的类型的最简单方法是什么?我尝试查找方法调用计数,以查看是否调用了某个构造函数,但是创建数百万个对象的所有对象都只是小的结构体类型。如果我理解正确,即使装箱,这些也不应对GC产生影响?
该算法创建了数十万个单独的结果点对象。当然,这些对象不应该被垃圾回收,因为它们代表操作的输出。但这引出了我的第二个问题:GC所花费的时间主要是取决于总对象数量还是实际收集的对象数量?我应该尝试限制结果对象的数量,而使用更少但更大的结果对象吗?
编辑:我使用VS 2010并发可视化器找到了在GC中所花费的时间。此外,在并行代码中,大多数阻塞线程的部分都在等待GC。
编辑:我应该澄清一下,性能问题是因为执行在工作站GC上实际上是串行化的。例如,参见此帖子中描述的性能问题。
我无法解决垃圾回收器阻塞我的线程的问题(而且我认为对于桌面应用程序,我不想使用服务器GC,对吗?)。因此,为了使这个操作线性加速,我需要减少调用GC的次数。浪费的大部分时间实际上是由其他线程阻塞等待一个线程执行GC造成的。
GC.Collect
吗?(也许是为了释放先前的结果集?) - Kieren Johnstone