C# .NETCore ZipArchive 处理大容量文件导致内存占用高的问题

发布于:2025-03-02 ⋅ 阅读:(64) ⋅ 点赞:(0)

        我们有一个文件 API,它定期安排特定路径(驱动器)的存档文件作业以备份数据。从 12 月 11 日起,该应用程序在监控仪表板下占用的内存使用量超过 3GB。 

        深入研究源代码后,我们可能会发现使用ZipArchive方法的一些潜在问题首先,我们要确保在处理流处理等管理资源时不会出现问题……其次,我们发现ZipArhcive可以采用不同的模式来处理压缩。因此,我们咨询了最热门的 AI 平台:ChatGPT。

        正如AI的答复,存档模式:update会将整个文件内容加载到内存中,这就是我们在压缩大量文件时面临高内存使用率的主要原因。

        下面是原始代码部分,我们可以重现 12 月 11 日的内存使用情况: 

string SizeConverter(long bytes)
{
var fileSize = new decimal(bytes);
var kilobyte = new decimal(1024);
var megabyte = new decimal(1024 * 1024);
var gigabyte = new decimal(1024 * 1024 * 1024);

switch (fileSize)
{
case var _ when fileSize < kilobyte:
return $"Less then 1KB";
case var _ when fileSize < megabyte:
return $"{Math.Round(fileSize / kilobyte, 0, MidpointRounding.AwayFromZero):##,###.##}KB";
case var _ when fileSize < gigabyte:
return $"{Math.Round(fileSize / megabyte, 2, MidpointRounding.AwayFromZero):##,###.##}MB";
case var _ when fileSize >= gigabyte:
return $"{Math.Round(fileSize / gigabyte, 2, MidpointRounding.AwayFromZero):##,###.##}GB";
default:
return "n/a";
}
}

Process currentProcess = System.Diagnostics.Process.GetCurrentProcess();
"------Start Archive------------".Dump();
currentProcess.Refresh();
SizeConverter(currentProcess.WorkingSet64).Dump();

var T1 = new Thread(() =>
{
var root = @"D:\Temp\Arch\";
var archiveDate = $"archive-{DateTime.Now:yyyyMMdd_HHmmss}.zip";
using var zipToOpen = new FileStream(root + archiveDate, FileMode.OpenOrCreate);
using var archive = new ZipArchive(zipToOpen, ZipArchiveMode.Update, false);

var files = new List<string>()
{
@"C:\Files\A_232MB.zip",
@"C:\Files\B_6MB.exe",
@"C:\Files\C_98MMB.exe",
@"C:\Files\D_3MB.pdf" ,
@"C:\Files\F_82MB.exe"
};

foreach (var relativePath in files)
{
var path = Path.Combine(root, relativePath);
archive.CreateEntryFromFile(path, relativePath);
}

});

T1.Start();


while(true)
{
Thread.Sleep(5000);

$"------After Archive------------{DateTime.Now}".Dump();
currentProcess.Refresh();
SizeConverter(currentProcess.WorkingSet64).Dump();

        结果表明,更新模式导致存档期间内存大幅增加,即使整个过程已完成。然后我们只需更改模式即可再次创建并触发相同的测试。下面的屏幕截图显示我们不再需要在相同场景中消耗大量内存。

        哇哦,说实话,ChatGPT 真的让我很惊讶。我知道人工智能不会总是给我们 100% 正确的答案,但我们可以根据自己的经验判断上下文并做出自己的解决方案😉。

如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。