c# - .NET GC 停止桌面应用程序 - 性能问题

标签 c# .net garbage-collection desktop-application

我正在开发一个大型 Windows 桌面应用程序,它以项目文件的形式存储大量数据。我们有自定义的 ORM 和序列化,可以有效地从 CSV 格式加载对象数据。该任务由并行运行的多个线程处理多个文件来执行。我们的大型项目可以包含数百万甚至更多的对象,它们之间有很多关系。

最近,我的任务是改进项目打开性能,该性能对于非常大的项目来说是恶化的。分析后发现,大部分时间都花在了垃圾收集 (GC) 上。

我的理论是,由于大量非常快速的分配,GC 被饿死,推迟了很长时间,然后当它最终启动时需要很长时间才能完成工作。两个相互矛盾的事实进一步证实了这个想法:

  1. 优化反序列化代码以更快地工作只会让事情变得更糟
  2. 在关键位置插入 Thread.Sleep 调用使加载速度更快

下面是 7 个第 2 代收集和大量 GC 时间百分比的缓慢加载示例。 Bad

下面是代码中带有休眠期的快速加载示例,以允许 GC 有一些时间。在这种情况下,我们有 19 个第 2 代集合,也是第 0 代和第 1 代集合数量的两倍多。 Good

那么,我的问题是如何防止这种 GC 饥饿?添加 Thread.Sleep 看起来很傻,而且很难在正确的位置猜测正确的毫秒数。我的另一个想法是使用 GC.Collect,但这也带来了放置它们的数量和位置的困难。还有其他想法吗?

最佳答案

根据评论,我猜你正在做大量的 String.Substring() 操作作为 CSV 解析的一部分。这些中的每一个都会创建一个新的字符串实例,我敢打赌您在将其进一步解析为整数或日期或您需要的任何内容后将其丢弃。您几乎肯定需要开始考虑使用不同的持久性机制(CSV 有很多您无疑知道的缺点),但与此同时您将想要研究不分配子字符串的解析器版本。如果深入研究 Int32.TryParse 的代码,您会发现它会进行一些字符迭代以避免分配更多字符串。我敢打赌,您可以花一个小时编写一个带有 startend 参数的版本,然后您可以将整行带偏移量传递给它们并避免执行子字符串调用以获取各个字段值。这样做将为您节省数百万的分配。

关于c# - .NET GC 停止桌面应用程序 - 性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33504105/

相关文章:

.net - 我对 async/await、它的工作原理及其优点的理解是否正确?

c# - DataGridView 列宽百分比

java - JVM 垃圾回收问题

c# - 识别扩展方法的反射(reflection)

c# - Linq to Entities - 针对查询语法与方法语法的预测

c# - 初始化对象时强制进行属性初始化

c# - 使用Object Initializer的复活区别

c# - 在 asp.net 应用程序中使用的类库中正确实现缓存

c# - 使用 ionic zip 时压缩失败

c# - 加载用户控件时显示 "User control is loading"消息