Bon*_*Lee 1 c# garbage-collection bitmap
我构建控制台应用程序来进行这样的测试。
while (true)
{
var bmp = new Bitmap(1600, 1200);
//var buffer = new byte[2000 * 1000 * 4];
Thread.Sleep(10);
}
Run Code Online (Sandbox Code Playgroud)
运行后,内存在很短的时间内增加到2GB以上。
这是 案例的日志Bitmap
。
[2017-04-27 12:15:03][00:00:01.0150128] PrivateBytes : 1583.0MB, AllHeapsBytes : 0.0MB, Thread Count : 23, CPU Usage : 12%
[2017-04-27 12:15:04][00:00:02.0019966] PrivateBytes : 2150.0MB, AllHeapsBytes : 0.0MB, Thread Count : 24, CPU Usage : 10%
[2017-04-27 12:15:05][00:00:03.0030021] PrivateBytes : 500.0MB, AllHeapsBytes : 4.1MB, Thread Count : 24, CPU Usage : 26%
[2017-04-27 12:15:06][00:00:04.0040047] PrivateBytes : 1043.0MB, AllHeapsBytes : 4.1MB, Thread Count : 24, CPU Usage : 9%
[2017-04-27 12:15:07][00:00:05.0050024] PrivateBytes : 1601.0MB, AllHeapsBytes : 4.1MB, Thread Count : 24, CPU Usage : 7%
[2017-04-27 12:15:08][00:00:06.0060058] PrivateBytes : 2136.0MB, AllHeapsBytes : 4.1MB, Thread Count : 24, CPU Usage : 9%
[2017-04-27 12:15:09][00:00:07.0069981] PrivateBytes : 2695.0MB, AllHeapsBytes : 4.1MB, Thread Count : 24, CPU Usage : 14%
Run Code Online (Sandbox Code Playgroud)
如果我像这样改成Bitmap
数组byte
,内存使用量是稳定的。
while (true)
{
//var bmp = new Bitmap(1600, 1200);
var buffer = new byte[2000 * 1000 * 4];
Thread.Sleep(10);
}
Run Code Online (Sandbox Code Playgroud)
这是数组情况的日志byte
。
[2017-04-27 12:25:09][00:00:01.0080196] PrivateBytes : 63.0MB, AllHeapsBytes : 31.0MB, Thread Count : 23, CPU Usage : 11%
[2017-04-27 12:25:10][00:00:02.0020012] PrivateBytes : 66.0MB, AllHeapsBytes : 46.2MB, Thread Count : 24, CPU Usage : 18%
[2017-04-27 12:25:11][00:00:03.0030496] PrivateBytes : 67.0MB, AllHeapsBytes : 47.1MB, Thread Count : 24, CPU Usage : 8%
[2017-04-27 12:25:12][00:00:04.0040530] PrivateBytes : 67.0MB, AllHeapsBytes : 47.1MB, Thread Count : 24, CPU Usage : 10%
[2017-04-27 12:25:13][00:00:05.0050386] PrivateBytes : 67.0MB, AllHeapsBytes : 47.1MB, Thread Count : 24, CPU Usage : 11%
[2017-04-27 12:25:14][00:00:06.0060466] PrivateBytes : 52.0MB, AllHeapsBytes : 31.9MB, Thread Count : 24, CPU Usage : 10%
[2017-04-27 12:25:15][00:00:07.0070521] PrivateBytes : 67.0MB, AllHeapsBytes : 47.1MB, Thread Count : 24, CPU Usage : 18%
Run Code Online (Sandbox Code Playgroud)
我知道如果我调用bmp.Dispose()
它就会变得稳定的内存使用。
我很好奇为什么Bitmap
垃圾收集速度很慢,为什么不是byte
数组。
Bitmap 是一个名为 gdiplus 的非托管图形库的包装类。它是根据该库的C++ 包装器建模的,正如您从文档中可以看出的那样,C# 程序员使其接近一对一匹配。方法和属性非常小,它们只是调用库函数。
并且该类对象非常小,它没有自己的字段,并且从其基类Image继承了3个字段。仅需要 24 字节的 GC 堆。在触发垃圾收集之前,您可以创建很多个,接近十万个。实际存储都是非托管的,在 gdiplus 库内,与宽度 * 高度成比例,具体取决于图像的像素格式。
仅当您调用 Dispose() 或垃圾收集器运行终结器时,才会释放非托管存储。.NET 程序员在第一次开始编程时几乎总是忽略 Dispose/using。他们总是在 Bitmap 见到制作者。
项目 > 属性 > 资源在这个故事中值得注意。它提供了非常方便的语法来在程序中使用位图资源。但这很危险,几乎没有人意识到每次在代码中使用 Properties.Resources.Somename 时,他们都会得到一个必须处理的全新 Bitmap 对象。
这种错误经常发生,以至于 Microsoft 决定在 WPF 中采用完全不同的方法。仍然是非托管图形库的包装类,更新的一个称为 WIC。但故意不实现 IDisposable。以及自动处理它的方案。.NET 框架代码调用 GC.Collect(),哎呀。但更难发现它的效果并不好。
归档时间: |
|
查看次数: |
1059 次 |
最近记录: |