C# 如何消除LOH片段并优化代码

C# 如何消除LOH片段并优化代码,c#,heap-memory,large-files,C#,Heap Memory,Large Files,我正在运行一个简单的线程来清除目录中的一些缓存文件。大多数文件都是大于80KB的大型对象。目录中大约有2000个这样的文件。结果如下所示 while (true) { if (Directory.Exists(CACHE_PATH)) { List<FileInfo> filesList = new DirectoryInfo(CACHE_PATH).GetFiles("*", SearchOption.AllDirectories).ToList(); lo

我正在运行一个简单的线程来清除目录中的一些缓存文件。大多数文件都是大于80KB的大型对象。目录中大约有2000个这样的文件。结果如下所示

while (true)
{
  if (Directory.Exists(CACHE_PATH))
  {
    List<FileInfo> filesList = new DirectoryInfo(CACHE_PATH).GetFiles("*", SearchOption.AllDirectories).ToList();
    long directorySize = filesList.Sum(e => e.Length);

    if (directorySize > CACHE_MAX_SIZE)
    {
      filesList.Sort(new FileInfoAccessTimeComparer());
      while (directorySize > CACHE_MAX_SIZE * 0.75)
      {
        directorySize -= filesList[0].Length;
        filesList[0].Delete();
        filesList.RemoveAt(0);
      }
    }
    filesList.Clear();
    filesList = null;
  }
  Thread.Sleep(CACHE_CLEANUP_INTERVAL);
}
我想知道这种方法是否会导致任何LOH碎片,以及除List之外我应该使用的任何其他类型的可枚举类型,比如ArrayPool

另外,这是一个好的使用方法吗

List<FileInfo> filesList = new DirectoryInfo(CACHE_PATH).GetFiles("*", SearchOption.AllDirectories).ToList();
而不是

FileInfo[] fileInfos = new DirectoryInfo(CACHE_PATH).GetFiles("*", SearchOption.AllDirectories);
List<FileInfo> filesList = fileInfos.ToList();

没有大对象堆问题,因为您的底层数组很小,只有几千个条目,而您的FileInfo对象很小。FileInfo只是元数据—它不是文件的内容

您的代码没有明显的问题。您可以避免使用RemoveAt来保存许多幕后不必要的阵列分配/调整大小操作。下面的代码可以实现这一点,也可以避免调用ToList:


注意:要像我一样使用ForEach,您需要安装。如果这是一个问题,请改用foreach循环

如果几千人增加到80人,或者十万人可能更多呢?会有什么影响?如果你使用我建议的更改,你会没事的。大型对象堆大约有80K。这不是那么多的记忆。最终,如果内存不足,GC将处理它。因此,总括而言,陆恭蕙不大可能介入。但如果这样做的话,我的代码可能会执行得更好,因为由于去掉RemoveAt,分配的数组应该会更少。我现在不想安装任何nuget软件包。@DimuthRuwantha在这种情况下,用ForEach循环替换我对ForEach的使用。代码的其余部分将保持不变。此外,这是一个很好的使用它们的方法,它们是相同的——不管ToList是否在自己的行上。
while (true)
{
    if (Directory.Exists(CACHE_PATH))
    {
        var filesList = new DirectoryInfo(CACHE_PATH).GetFiles("*", SearchOption.AllDirectories);
        long directorySize = filesList.Sum(e => e.Length);

        if (directorySize > CACHE_MAX_SIZE)
        {
            filesList.OrderBy(z => z, new FileInfoAccessTimeComparer()).TakeWhile(z => directorySize > CACHE_MAX_SIZE * 0.75)
                .ForEach(z =>
                {
                    z.Delete();
                    directorySize -= z.Length;
                });
        }
        filesList = null;
    }
    Thread.Sleep(CACHE_CLEANUP_INTERVAL);
}