垃圾收集和Parallel.ForEach问题VS2015升级后 [英] Garbage Collection and Parallel.ForEach Issue After VS2015 Upgrade

查看:421
本文介绍了垃圾收集和Parallel.ForEach问题VS2015升级后的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些code在我自己的R-如C#数据框类处理几百万的数据行。有要求遍历并行数据行的一些Parallel.ForEach的。这code已经超过一年使用VS2013和.NET 4.5没有问题一直运行。

I have some code to process several million data rows in my own R-like C# DataFrame class. There's a number of Parallel.ForEach calls for iterating over the data rows in parallel. This code has been running for over a year using VS2013 and .NET 4.5 without issues.

我有两个开发机器(A和B)和最近升级机器A到VS2015。我开始注意到我的code奇怪的间歇冻结半年左右的时间。让它运行很长一段时间,事实证明,在code没有最终完成。它只是需要15-120分钟,而不是1-2分钟。

I have two dev machines (A and B) and recently upgraded machine A to VS2015. I started noticing a strange intermittent freeze in my code about half the time. Letting it run for a long time, it turns out that the code does eventually finish. It just takes 15-120 minutes instead of 1-2 minutes.

努力打破所有使用VS2015调试器持续出现故障的某些原因。所以,我插了一堆日志报表。事实证明,当有一个Parallel.ForEach环(前后各Parallel.ForEach循环之后比较集合计数)期间收集的第二代出现这种冻结。整个额外13-118分钟都花在里面取Parallel.ForEach循环调用发生了第二代集合(如果有的话)重叠。如果有任何期间循环Parallel.ForEach第二代无集合(当我运行时间约50%),那么一切都结束在1-2分钟罚款。

Attempts to Break All using the VS2015 debugger keep failing for some reason. So I inserted a bunch of log statements. It turns out that this freeze occurs when there is a Gen2 collection during a Parallel.ForEach loop (comparing the collection count before and after each Parallel.ForEach loop). The entire extra 13-118 minutes is spent inside whichever Parallel.ForEach loop call happens to overlap with a Gen2 collection (if any). If there are no Gen2 collections during any Parallel.ForEach loops (about 50% of the time when I run it), then everything finishes fine in 1-2 minutes.

当我运行计算机A上VS2013相同code,我得到同样的冻结。当我在机器B(这是从来没有升级)VS2013运行code,它完美的作品。它跑了几十个时间无结冰过夜。

When I run the same code in VS2013 on Machine A, I get the same freezes. When I run the code in VS2013 on Machine B (which was never upgraded), it works perfectly. It ran dozens of time overnight with no freezing.

有些事情我注意到/试过:

Some things I've noticed / tried:


  • 的冻结发生有或无连接计算机A上的调试器(我想这是一些与起初VS2015调试器)

  • 的冻结发生,我是否建立在调试或发布模式

  • 的冻结发生,如果我的目标.NET 4.5或.NET 4.6

  • 我试图禁用RyuJIT但是这并没有影响到冻结

我不会改变默认设置GC在所有。据GCSettings,所有运行与LatencyMode互动和IsServerGC假的发生。

I'm not changing the default GC settings at all. According to GCSettings, all runs are happening with LatencyMode Interactive and IsServerGC as false.

我可以在每次调用之前Parallel.ForEach切换到LowLatency,但我真的preFER明白发生了什么事情。

I could just switch to LowLatency before every call to Parallel.ForEach, but I'd really prefer to understand what's going on.

有其他人看到在Parallel.ForEach奇怪的冻结后,VS2015升级?上有什么好下一步将是什么想法?

Has anyone else seen strange freezes in Parallel.ForEach after the VS2015 upgrade? Any ideas on what a good next step would be?

更新1:添加一些示例code上述含糊不清的解释...

下面是一些示例code,我希望将证明这个问题。这code B中的机器上10-12秒运行,始终如一。它遇到了一些第二代藏品,但他们采取几乎没有时间。如果我取消这两个GC设置行,我可以迫使它没有第二代的集合。这有点慢,然后在30-50秒。

Here is some sample code that I hope will demonstrate this issue. This code runs in 10-12 seconds on B machine, consistently. It encounters a number of Gen2 collections, but they take almost no time at all. If I uncomment the two GC settings lines, I can force it to have no Gen2 collections. It's somewhat slower then at 30-50 seconds.

现在我的机器上,在code需要的一个随机时间。似乎是5至30分钟之间。它似乎变得更糟,它遇到的第二代多藏品。如果我取消这两个GC设置行,它需要30-50秒,机器A还(同机B)。

Now on my A machine, the code takes a random amount of time. Seems to be between 5 and 30 minutes. And it seems to get worse, the more Gen2 collections it encounters. If I uncomment the two GC settings lines, it takes 30-50 seconds on Machine A also (same as Machine B).

有可能采取的行和数组大小的数量而言一些调整为这对显示另一台机器上。

It might take some tweaking in terms of the number of rows and array size for this to show up on another machine.

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using System.Linq;
using System.Runtime;    

public class MyDataRow
{
    public int Id { get; set; }
    public double Value { get; set; }
    public double DerivedValuesSum { get; set; }
    public double[] DerivedValues { get; set; }
}

class Program
{
    static void Example()
    {
        const int numRows = 2000000;
        const int tempArraySize = 250;

        var r = new Random();
        var dataFrame = new List<MyDataRow>(numRows);

        for (int i = 0; i < numRows; i++) dataFrame.Add(new MyDataRow { Id = i, Value = r.NextDouble() });

        Stopwatch stw = Stopwatch.StartNew();

        int gcs0Initial = GC.CollectionCount(0);
        int gcs1Initial = GC.CollectionCount(1);
        int gcs2Initial = GC.CollectionCount(2);

        //GCSettings.LatencyMode = GCLatencyMode.LowLatency;

        Parallel.ForEach(dataFrame, dr =>
        {
            double[] tempArray = new double[tempArraySize];
            for (int j = 0; j < tempArraySize; j++) tempArray[j] = Math.Pow(dr.Value, j);
            dr.DerivedValuesSum = tempArray.Sum();
            dr.DerivedValues = tempArray.ToArray();
        });

        int gcs0Final = GC.CollectionCount(0);
        int gcs1Final = GC.CollectionCount(1);
        int gcs2Final = GC.CollectionCount(2);

        stw.Stop();

        //GCSettings.LatencyMode = GCLatencyMode.Interactive;

        Console.Out.WriteLine("ElapsedTime = {0} Seconds ({1} Minutes)", stw.Elapsed.TotalSeconds, stw.Elapsed.TotalMinutes);

        Console.Out.WriteLine("Gcs0 = {0} = {1} - {2}", gcs0Final - gcs0Initial, gcs0Final, gcs0Initial);
        Console.Out.WriteLine("Gcs1 = {0} = {1} - {2}", gcs1Final - gcs1Initial, gcs1Final, gcs1Initial);
        Console.Out.WriteLine("Gcs2 = {0} = {1} - {2}", gcs2Final - gcs2Initial, gcs2Final, gcs2Initial);

        Console.Out.WriteLine("Press Any Key To Exit...");
        Console.In.ReadLine();
    }

    static void Main(string[] args)
    {
        Example();
    }
}

更新2:刚搬东西出来的意见,为未来的读者...

此修复程序:<一href=\"https://support.microsoft.com/en-us/kb/3088957\">https://support.microsoft.com/en-us/kb/3088957完全修复该问题。我没有看到在所有的速度缓慢的问题后应用。

This hotfix: https://support.microsoft.com/en-us/kb/3088957 totally fixes the issue. I'm not seeing any slowness issues at all after applying.

原来,不要有什么关系Parallel.ForEach我在此基础上认为:<一href=\"http://blogs.msdn.com/b/maoni/archive/2015/08/12/gen2-free-list-changes-in-clr-4-6-gc.aspx\">http://blogs.msdn.com/b/maoni/archive/2015/08/12/gen2-free-list-changes-in-clr-4-6-gc.aspx虽然修补程序提到Parallel.ForEach出于某种原因。

It turned out not to have anything to do with Parallel.ForEach I believe based on this: http://blogs.msdn.com/b/maoni/archive/2015/08/12/gen2-free-list-changes-in-clr-4-6-gc.aspx though the hotfix does mention Parallel.ForEach for some reason.

推荐答案

它看起来像问题现在已解决,看的http://blogs.msdn.com/b/maoni/archive/2015/08/12/gen2-free-list-changes-in-clr-4-6-gc.aspx

It looks like the problem has been addressed now, see http://blogs.msdn.com/b/maoni/archive/2015/08/12/gen2-free-list-changes-in-clr-4-6-gc.aspx

这篇关于垃圾收集和Parallel.ForEach问题VS2015升级后的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆