C#-SelectMany使用ReactiveExtensions占用大量内存
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了C#-SelectMany使用ReactiveExtensions占用大量内存,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含2293字,纯文字阅读大概需要4分钟。
内容图文
我想创建一个接收图像并返回一些派生对象的管道.
我正在使用一系列位图,对于每个位图我都执行任务(即异步).如此简单.但是,我发现内存消耗确实很高.为了说明问题,我创建了可以运行的测试.
请查看一下内存,因为它将占用多达400 MB的RAM.
我该怎么做才能避免占用太多内存?这里发生了什么事?
[Fact]
public async Task BitmapPipelineTest()
{
var bitmaps = Enumerable.Range(0, 100).Select(_ => new WriteableBitmap(800, 600, 96, 96, PixelFormats.Bgr24, new BitmapPalette(new List<Color>() { new Color() })));
var bitmapsObs = bitmaps.ToObservable();
var processed = bitmapsObs.SelectMany(bitmap => DoSomethingAsync(bitmap));
processed.Subscribe();
await Task.Delay(20000);
}
private async Task<object> DoSomethingAsync(BitmapSource bitmap)
{
await Task.Delay(1000);
return new object();
}
解决方法:
因此,我认为该问题不一定是由于SelectMany甚至是响应式扩展引起的.看起来WriteableBitmap使用的是非托管内存:source code.我认为问题是,您正在非常连续地创建一堆相对较小的托管对象,这些对象占用了大量的非托管内存.从MSDN:
If a small managed object allocates a large amount of unmanaged memory, the runtime takes into account only the managed memory, and thus underestimates the urgency of scheduling garbage collection.
但是我们可以通过使用GC.AddMemoryPressure和GC.RemoveMemoryPressure函数来给垃圾收集器提示.这将有助于GC改进其计划.在进行此操作之前,我们需要对分配的非托管内存量有所了解.我相信非托管内存用于存储像素阵列,因此我认为一个很好的估计是像素宽度乘以像素高度乘以每个通道中的位数乘以通道数.从MSDN开始,每个通道和4个通道看起来有32位(4个字节).
我使用类似于以下代码的代码运行了一些测试,并获得了很好的结果:
var processed =
Enumerable
.Range(0, 100)
.Select(_ => new WriteableBitmap(
800,
600,
96,
96,
PixelFormats.Bgr24,
new BitmapPalette(new List<Color>() { new Color() })))
.Select(x => new { Bitmap = x, ByteSize = x.PixelWidth * x.PixelHeight * 4 * 4)
.ToObservable()
.Do(x => GC.AddMemoryPressure(x.ByteSize))
.SelectMany(x => DoSomethingAsync(x.Bitmap));
processed
.Subscribe(x => GC.RemoveMemoryPressure(x.ByteSize));
但是,如果您的源发布位图的速度比处理位图的速度快,那么您仍然会遇到问题.背压将导致内存分配的速度快于释放内存的速度.
不过,老实说,您是否真的将位图推送给您?我不知道您的实际程序是什么样的,但是在您的示例代码中,这显然是基于拉的系统.如果是基于拉动的系统,您是否考虑过PLINQ? PLINQ非常适合这类事情.它使您可以很好地控制并发性,而不必担心背压.
内容总结
以上是互联网集市为您收集整理的C#-SelectMany使用ReactiveExtensions占用大量内存全部内容,希望文章能够帮你解决C#-SelectMany使用ReactiveExtensions占用大量内存所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。