【发布时间】:2021-03-22 11:42:00
【问题描述】:
我正在开发的 C#/.NET 应用程序使用了巨大的字节数组,并且存在内存碎片问题。使用 CLRMemory 检查内存使用情况
我们使用的代码如下
PdfLoadedDocument loadedDocument = new PdfLoadedDocument("myLoadedDocument.pdf");
// Operations on pdf document
using (var stream = new MemoryStream())
{
loadedDocument.Save(stream);
loadedDocument.Close(true);
return stream.ToArray(); //byte[]
}
我们在应用程序的多个位置使用类似的代码,我们将其称为循环以生成从几百到 10000 的批量审计
- 现在有更好的方法来处理这个问题以避免碎片化
作为审计的一部分,我们还使用以下代码从 Amazon S3 下载大文件
using (var client = new AmazonS3Client(_accessKey, _secretKey, _region))
{
var getObjectRequest = new GetObjectRequest();
getObjectRequest.BucketName = "bucketName";
getObjectRequest.Key = "keyName";
using (var downloadStream = new MemoryStream())
{
using (var response = await client.GetObjectAsync(getObjectRequest))
{
using (var responseStream = response.ResponseStream)
{
await responseStream.CopyToAsync(downloadStream);
}
return downloadStream.ToArray(); //byte[]
}
}
}
- 有没有更好的替代方法来下载大文件而不将它们移动到 LOH,这会对垃圾收集器造成影响
【问题讨论】:
-
可能在写入数据之前运行 GC 以减少碎片。
-
@jdweng,我们循环调用,每次调用 GC 可能会严重影响 CPU 性能,因为在此操作期间将占用所有其他资源
-
在循环之前调用 GC。只要为循环中最大的对象清除了足够的连续内存,using 语句就应该处理对象,因此您不应该碎片化。
-
恐怕这可能无济于事,因为由于内部逻辑而发生碎片并且我们已经对每个 IDisposable 对象进行了处置。所以在外面调用 GC 可能会产生零到可以忽略不计的影响。并不总是建议显式调用 GC。
标签: c# arrays memory-management memory-fragmentation