c# - for循环进入0% cpu hang

标签 c# .net for-loop clr

我需要获取一个文件列表,将它们修剪到目录路径并返回一个不同的列表。在某些情况下,这可能会处理超过 500 万个文件。

我遇到了一个问题,即核心进程因 CPU 使用率 0% 而挂起,原因我无法确定。

var filePaths = File.ReadAllLines("list_of_files.txt");
// ...
blockSw.Restart();
int[] curCounter = new int[1];
Stopwatch groupSw = Stopwatch.StartNew();
Parallel.For(0, filePaths.LongLength, i =>
  {
    //Trim the filename, if it exists, off of every
    // entry that we read out of the input file
    filePaths[i] = (Path.GetDirectoryName(filePaths[i]));
    //This can be used to safely report status
    // little hack-y, though
    lock (curCounter)
    {
        curCounter[0]++;
        if (curCounter[0] % 100000 == 0)
        {
            Trace.WriteLine(curCounter[0].ToString() + " rows complete in "
                + groupSw.ElapsedMilliseconds
                + " ; total time: " + blockSw.ElapsedMilliseconds);
            groupSw.Restart();
        }
    }
  }
);
blockSw.Stop();
Trace.WriteLine("Completed path truncation in " + blockSw.ElapsedMilliseconds + "ms.");

然后输出看起来像这样:

100000 rows complete in 266 ; total time: 266
200000 rows complete in 239 ; total time: 507
300000 rows complete in 843 ; total time: 1351
400000 rows complete in 1058 ; total time: 2411
...
1100000 rows complete in 3480 ; total time: 11602
1200000 rows complete in 432 ; total time: 12036
1300000 rows complete in 342 ; total time: 12379
...
4800000 rows complete in 832 ; total time: 48617
4900000 rows complete in 377 ; total time: 48996
5000000 rows complete in 2841 ; total time: 51839
5100000 rows complete in 1285 ; total time: 53126
Completed path truncation in 148124ms.

注意最后两行... 53 秒完成所有操作,然后循环结束,我们坐下来等待约 90 秒。观察 TaskManager 中的进程,我可以看到它在此期间仅以 0% 的 CPU 闲置。

关于这里发生了什么或我可以在哪里寻找线索的任何线索?

列出文件路径的输入文件约为 400MB,在此过程中 TaskManager 报告的内存大小约为 900MB。在测试期间,有大量可用物理 RAM 高于此数量。

移除循环内状态报告不会对性能产生任何影响 - 在循环结束时,我们仍然会遇到约 90 秒的 0% CPU 使用率挂起。

我对标准 for 循环而不是 Parallel.For 有同样的问题。


更新/解决方案

感谢克里斯、 jack 和汉斯。有了 Chris 无法重现的输入和 Hans 对 Break All 的建议,我能够缩小问题的范围。进一步调试,我发现实际问题是 Path.GetDirectoryName 是罪魁祸首。虽然它在几乎每个文件路径上都以 0-15 毫秒的速度运行,但有几十个路径需要长达 2 分钟的时间来处理。我注意到这些路径中都包含 ~ 。我仍然不清楚为什么它在根本不使用 CPU 的情况下执行此操作,但足以让我理解它是 Path 内部的并且加速它的唯一方法是重新实现 GetDirectoryName.

最佳答案

至于distinct.
可能不会比全部执行然后执行单个 LINQ 更快,但它应该占用更少的内存。

using (StreamReader sr = new StreamReader("TestFile.txt"))
{
   String line;
   String path;
   HashSet<string> paths = HashSet<string>(StringComparer.OrdinalIgnoreCase);
   // Read and process lines from the file until the end of
   // the file is reached.
   while ((line = sr.ReadLine()) != null)
   {
       Console.WriteLine(line);
       path = Path.GetDirectoryName(line);
       if(!String.IsNullOrEmpty(path)) paths.Add(path.Trim());
   }
}

关于c# - for循环进入0% cpu hang,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21207903/

相关文章:

php - 无法使用PHP将所有数据插入MySQL

c# - 繁重的计算分析/优化

.net - 有哪些带有源代码的大型 .NET 项目?

.net - 如何使用 AES 加密单个 block ?

iOS Swift 2 - 递归或迭代

c - 为什么在 C 语言的嵌套 for 循环中 scanf() 被跳过?

c# - 从 Ubuntu 中的其他 C# 服务访问自签名 HTTPS C# 服务

c# - 从 XML 文件创建嵌套节点的属性列表

c# - 获取文本文件中第一个字符的数量?

c# - 使用选定文件打开 Windows 资源管理器(或焦点,如果存在)的代码