You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

执行指定C#代码时CPU占用过高问题排查求助

排查C#代码导致CPU峰值问题

问题代码

public bool CheckIfValidSignedPdfExists(string fileServerPath, int memberagreementId)
{
    var filePaths = Directory.GetFiles(fileServerPath);

    if (filePaths.Length < 2)
    {
        return false;
    }

    var fileInfo = new List<FileInfo>();
    foreach (var path in filePaths)
    {
        if (File.Exists(path))
            fileInfo.Add(new FileInfo(path));
    }
    if (fileInfo.Count < 2)
        return false;

    else
    {
        fileInfo = fileInfo.OrderByDescending(x => x.LastWriteTimeUtc).Take(2).ToList();
        //Rules: 1. Name 2.size 3. Last write time 4. Extension
        var firstPdf = fileInfo.FirstOrDefault();
        var lastPdf = fileInfo.LastOrDefault();

        var firstFileNameCheck = string.Concat(Convert.ToString(memberagreementId), ".pdf");
        var lastFileNameCheck = lastPdf.Name.StartsWith(Convert.ToString(memberagreementId) + "-")
            && lastPdf.Name.EndsWith(".pdf", StringComparison.OrdinalIgnoreCase);

        if ((firstPdf.Name.Equals(firstFileNameCheck, StringComparison.OrdinalIgnoreCase)) &&
            (lastFileNameCheck) && (firstPdf.Length > lastPdf.Length) && (firstPdf.LastWriteTimeUtc >= lastPdf.LastWriteTimeUtc))
            return true;
        else
            return false;
    }
}

问题现象

运行上述代码时,CPU出现明显峰值,监控显示高CPU线程与这段代码直接关联,同时存在明确的CPU尖峰波动。

问题排查与分析

  1. 全量文件枚举的开销:Directory.GetFiles会一次性加载目录下所有文件的路径到内存,若目标目录包含大量文件(尤其是网络共享目录),该操作会阻塞线程并消耗大量CPU资源,IO延迟还会加剧线程调度的开销。
  2. 冗余的文件存在性检查:Directory.GetFiles返回的路径本身已保证存在(枚举期间文件被删除的极端情况除外),额外的File.Exists(path)检查重复发起IO请求,累积增加CPU和IO负载。
  3. 全量排序的高复杂度:代码对目录下所有FileInfo实例按LastWriteTimeUtc排序,排序算法的时间复杂度为O(n log n),当文件数量较多时,该操作会成为CPU消耗的核心点。
  4. 网络路径的IO放大效应:若fileServerPath是网络共享路径,文件系统操作的延迟会大幅增加,线程在等待IO时的上下文切换会进一步推高CPU使用率。

优化建议

  • 改用延迟枚举减少内存占用:用Directory.EnumerateFiles替代Directory.GetFiles,它会逐个返回文件路径,无需一次性加载所有数据到内存。
  • 提前过滤目标文件:枚举时直接筛选与memberagreementId相关的PDF文件,减少后续处理的数据量:
    var targetIdStr = memberagreementId.ToString();
    var relevantFiles = Directory.EnumerateFiles(fileServerPath, "*.pdf")
                                 .Where(path => 
                                     Path.GetFileName(path).Equals($"{targetIdStr}.pdf", StringComparison.OrdinalIgnoreCase)
                                     || Path.GetFileName(path).StartsWith($"{targetIdStr}-", StringComparison.OrdinalIgnoreCase))
                                 .Select(path => new FileInfo(path))
                                 .ToList();
    
  • 移除冗余的存在性检查:删除File.Exists(path)的判断,避免重复IO操作。
  • 缩小排序范围:仅对筛选后的目标文件排序,而非全目录文件,大幅降低排序的CPU开销。
  • 添加缓存机制:若该方法被频繁调用,可缓存目标文件的元数据(如文件名、修改时间、大小),定期刷新缓存,避免重复的IO和计算操作。

内容的提问来源于stack exchange,提问作者Puneet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 07:45:49