我正在运行一个简单的线程来清理目录中的一些缓存文件。大多数文件都是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();
答案 0 :(得分:1)
没有大对象堆问题,因为您的基础数组很小(只有几千个条目)并且您的FileInfo
对象很小。 FileInfo
只是元数据 - 它不是文件的内容。
您的代码没有明显的问题。您可以避免使用RemoveAt
来保存许多(幕后)不必要的数组分配/调整大小操作。以下代码将实现这一目标(并且还避免需要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);
}
请注意,要像我一样使用ForEach
,您需要安装MoreLINQ。如果这是一个问题,请改为使用foreach
循环。