【问题标题】:.NET Parallel Tasks gets slow after a while.NET 并行任务一段时间后变慢
【发布时间】:2024-05-22 07:00:01
【问题描述】:

我有一个应用程序,它通过执行 ICR 识别并根据坐标切割 tiff 文件的某些字段来处理 tiff 图像,然后将每个图像块保存到数据库中。我们每分钟需要处理很多图像,所以我们需要有多个线程同时处理图像。

应用程序运行的环境是 Windows Server 2012 DataCenter 版本,具有 256GB 的 RAM、2 个 Intel Xeon 处理器(每个 18 核)和 7 个 RAID 0 配置的 SSD 驱动器或类似的东西。

因此,我们预计最多可以并行运行 28 个线程。为此,我们使用 TPL 库来启动并行任务。这是一个代码示例:

private void btnIniciar_Click(object sender, EventArgs e) {    
    if (managerTokensCancelacion != null)
        managerTokensCancelacion.Dispose();

    managerTokensCancelacion = new CancellationTokenSource();
    tokenCancelacion = managerTokensCancelacion.Token;

    for (int cnt = 0; cnt < 28; cnt++) {
        Task.Factory.StartNew(myAction(cnt+1), tokenCancelacion);
    }

}

private Action myAction(int numThread) {
    return () => {
        try {
            while (true) {
                (new BusinessClass()).splitAndReadImage(numThread)); 
                tokenCancelacion.ThrowIfCancellationRequested();
            }
        }
        catch (OperationCanceledException ex) {
            Console.WriteLine("Cancelled process");
        }
    };
}

我们有一个业务类来处理所有的逻辑,但基本功能是在数据库中搜索图像(我们有我们的并发机制来避免不同的线程处理同一个图像)。我们处置所有对象以避免内存泄漏。

问题是,应用程序在最初的一两分钟内运行良好,具体取决于我启动了多少进程。如图所示,它使用了所有核心(这不是生产服务器,但它有 8 个核心)。

但是,当我处理近 400 张图像时,它会变慢,并且任务可能仅使用一个内核按顺序运行。

我的代码有什么地方做错了吗?正如我之前提到的,我们没有内存泄漏问题,它使用相同的内存运行并且不会持续增加,我们在每次迭代中处理所有对象,但突然变慢并停止使用所有可用内核。也许是关于 Windows Server 的?还是 TPL 库的错误?数据库查询在每次迭代时运行良好。

【问题讨论】:

  • 你的splitAndReadImage在做什么?从数据库中读取?
  • 是的。接下来是流程: 1. 从数据库中获取图像 2. 当它找到它时,我有一个先前加载到我的应用程序中的坐标数组 3. 我遍历这个数组切割每一块 4. 我将每一块保存在数据库 5. 最后,我更新了一个我得到完整图像的字段,表明我已经处理它没有问题。
  • 我怀疑你的代码是同步的,不允许其他线程访问相同的资源?所以只使用一个线程,因此只有一个核心。为了阻止我们猜测并给出答案,您需要发布splitAndReadImage的相关代码。如果它涉及数据库,则最好使用异步数据库调用。
  • 我们需要看到你流程中的主要核心逻辑。
  • 我已经调试了很多代码,查询并没有变慢,查询时间几乎一直都一样。

标签: c# .net task-parallel-library windows-server-2012


【解决方案1】:

我建议您在“时间轴”模式下尝试 JetBrains dotTrace 分析器。 https://www.jetbrains.com/profiler/help/Analyzing_Concurrency_Profiling_Results_Timeline_.html

它将非常准确地向您展示您的应用程序变慢的原因 - 它是由于垃圾收集或任何 IO 操作而发生的。

【讨论】:

    最近更新 更多