【问题标题】:C# ThreadPool application performance degrading over timeC# ThreadPool 应用程序性能随着时间的推移而下降
【发布时间】:2012-05-09 20:02:18
【问题描述】:

我有一个类,比如“MyComputation”,它在一个长构造函数中进行大量计算。单独执行时(没有磁盘 i/o 或网络操作)通常需要大约 20 毫秒才能运行。这个类的大约 100 个实例由父类创建,比如“ComputeParent”,它将它们作为工作项在 ThreadPool 中排队:

ThreadPool.QueueUserWorkItem(myComputationCall, my_computation_data);

“myComputationCall”看起来像这样:

    public static void myComputationCall(Object my_computation_data)
    {
        try
        {
            MyDataObject data = (MyDataObject)my_computation_data;

            var computation_run = new MyComputation(data.parameter1, data.parameter2);

            data.result = computation_run.result;
        }
        finally
        {
            if (Interlocked.Decrement(ref num_work_items_remaining) == 0)
                done_event.Set();
        }
    }

done_event 是一个静态 ManualResetEvent:

    private static ManualResetEvent done_event;

    ...

    done_event = new ManualResetEvent(false);

对于各种输入参数,我运行 ComputeParent 大约 500 次。所以我有很多嵌套类。问题是执行 ComputeParent 所需的时间逐渐增加。运行每个特定 ComputeParent 所需的时间会有一定的差异,但时间量会相当稳定地增加(从几何上讲,每次连续迭代需要更长的时间)。

程序的内存消耗不会随着时间的推移而显着增加,尽管它相当高(~300MB)。它运行在具有 8 个逻辑核心的计算机上,处理器的使用似乎非常突发。我不确定还有什么可能与该问题相关。

我希望不必通过批处理文件运行 ComputeParent,尽管这样做后似乎不会出现问题。

【问题讨论】:

  • 有什么理由(比如 .NET
  • 您应该开始分析。衡量就是知道。可能是 GC 活动增加,其他线程,......这段代码中没有明显的线索。
  • 你试过分析它吗?我也推荐使用 TPL。
  • 我不知道 TPL,我会尝试的。我还将分析我拥有的东西,看看瓶颈是什么。谢谢
  • Henk,你是对的,有大量的垃圾收集活动(第 2 代对象)。我切换到 Parallel.ForEach 并且性能不再下降。代码也简单一些。谢谢亨克,西蒙。

标签: c# multithreading performance threadpool


【解决方案1】:

如果 ThreadPool 中的可用线程数变为 0,并且您继续添加新的工作项,那么新添加的工作项将“等待”。这意味着您的 ComputeParent 将等待它的“myComputationCall”实例。启动越来越多的 ComputeParent 会导致它们的平均执行时间增加。

【讨论】:

    【解决方案2】:

    这个问题已经回答了。感谢所有的海报。

    对于其他有类似问题的人,我建议使用 Henk 建议的任务并行库。

    【讨论】:

      猜你喜欢
      • 2014-04-15
      • 1970-01-01
      • 2010-10-07
      • 1970-01-01
      • 1970-01-01
      • 2016-09-11
      • 1970-01-01
      • 2016-11-06
      • 2021-07-17
      相关资源
      最近更新 更多