Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/294.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# .NET GC正在暂停桌面应用程序-性能问题_C#_.net_Garbage Collection_Desktop Application - Fatal编程技术网

C# .NET GC正在暂停桌面应用程序-性能问题

C# .NET GC正在暂停桌面应用程序-性能问题,c#,.net,garbage-collection,desktop-application,C#,.net,Garbage Collection,Desktop Application,我正在开发一个大型windows桌面应用程序,它以项目文件的形式存储大量数据。我们有自己的定制ORM和序列化,可以有效地从CSV格式加载对象数据。此任务由并行处理多个文件的多个线程执行。我们的大型项目可以包含数百万个甚至更多的对象,它们之间有许多关系 最近,我接到了改善项目开放性能的任务,对于非常大的项目来说,这种性能会恶化。分析后发现,花费的大部分时间都可以归因于垃圾收集(GC) 我的理论是,由于大量非常快速的分配,GC被饿死,延迟了很长时间,然后当它最终启动时,需要很长时间才能完成工作。两个

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

最近,我接到了改善项目开放性能的任务,对于非常大的项目来说,这种性能会恶化。分析后发现,花费的大部分时间都可以归因于垃圾收集(GC)

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

  • 优化反序列化代码以更快地工作只会让事情变得更糟
  • 在战略位置插入
    Thread.Sleep
    调用可以加快加载速度
  • 下面是7个第2代集合的缓慢加载和GC中大量时间的示例。

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


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

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

    因此,这似乎是一个.NET错误,而不是GC饥饿。本问题中描述的变通方法和答案完全适用。通过切换到GC服务器模式,我得到了最好的结果


    但是请注意,我在.NET 4.5.2中遇到了这个问题。如果有热修复程序链接,将添加。

    我想知道线程是如何/为什么的。睡眠使事情变得更快了?要快多少?我在创建大量重复字符串变量,然后作为序列化的一部分取消引用的情况下见过这种行为。您使用什么样的序列化来加载项目文件?所有加载都在后台线程上完成,所以我假设sleep允许GC线程启动。从上面的图片中你可以看到,一旦我们引入睡眠,我们的睡眠时间从4分钟变为25秒。减慢速度:)GC由分配触发。如果您睡眠,则在此期间不会触发GC。我发现GC饥饿理论的证据非常薄弱。@HansPassant在对这个问题答案的评论中看到了这个问题-看起来这个错误已经用热修复程序修复了。我需要就有效的CSV解析这个主题提出单独的问题。问题是.NET促使您使用字符串,因为您可以方便地使用StreamReader.ReadLine、String.Split和Single.TryParse来处理字符串。大多数可用的CSV解析器都能做到这一点……希望有一个可变的字符串,我可以反复使用。