【问题标题】:Reuseable buffer with variable length可变长度的可重用缓冲区
【发布时间】:2015-08-13 12:16:24
【问题描述】:
  • 我正在从相机或视频文件中抓取帧。
  • 我想从每一帧(位图)裁剪矩形并将其保存在内存中。
  • 处理新框架时,我不再需要旧的裁剪矩形。我可以用新的裁剪矩形覆盖它。

显然,我不能为每个帧创建新的字节数组并依赖垃圾收集,因为我很容易耗尽内存,或者至少内存会非常碎片化。我需要重用一些缓冲区。

如果裁剪矩形的大小是恒定的,那会很容易,但在每一帧中它可能不同(视频中的图像对象跟踪)。

是否有任何 API 可以帮助我进行内存管理?我尝试重用 MemoryStream,但我不确定这是否是正确的做法:

if (memoryStream == null)
{
   memoryStream = new MemoryStream(1024*10);
}
else
{
   memoryStream.Position=0;   //
   memoryStream.SetLength(0); //"clear" memoryStream, but hopefully keeps underlying buffer allocated/
}

croppedBitmap.Save(memoryStream, ImageFormat.Png);

【问题讨论】:

  • “显然,我不能......依赖垃圾收集” - 哦,所以你已经尝试过并测量了它?愿意分享结果吗?还是您假设 GC 无法完成这项工作?
  • 几秒钟后我出现内存不足异常和高内存使用率(数百兆字节)
  • 请尝试准确地解释您要做什么。例如,您需要在内存中存储多少帧?
  • @Liero - 啊,所以你的意思是你有内存泄漏,而不是修复它,你会责怪 GC?
  • @ Robinson - 我只想将最后一张裁剪的图像保存在内存中。 @Damien_The_Unbeliever:我不是在责怪 GC。而且我没有内存泄漏,确切地说。但这需要 GC 每秒清理一次内存,效率不高。如果您经常分配大型对象,即使您处置它们或不保留对它们的引用,您也很容易耗尽内存。另一件事是,如果 GC 收集太频繁,它会将许多其他对象移动到更高代,而且也不健康,恕我直言

标签: c# memory-management


【解决方案1】:

选项:

  1. 您可以在内存中将图像保存为Bitmap。确实不需要将其序列化为 PNG。您可以重复使用该 Bitmap 对象。
  2. 您可以编写自己的类似MemoryStream 的流,永远重复使用同一个缓冲区。

【讨论】:

  • croppedBitmap 实际上是 System.Drawing.Bitmap 对象。问题是,这个位图不拥有底层位图数据。如果我不保存它(无论是什么格式 - png 或 raw),当我抓取新帧时,数据会在我眼前发生变化。原因是,croppedBitmap 只指向与加载整个帧的缓冲区相同的内存(在这种情况下由 EmguCV)
  • 好的,创建您拥有的第二个位图并使用 Graphics 对象复制您需要保存的像素。实际上,如果你快速处理掉它们,创建大量位图的 GC 负载非常低。一个 Bitmap 对象只是几个字节 + 一个巨大的非托管缓冲区。
  • 好的,但这会在每一帧中分配和释放巨大的非托管缓冲区,而且成本很高,不是吗?
  • 那就不要每帧都释放。重复使用位图。 (它实际上并没有那么贵,它是一个 memset(0))。这回答了你的问题了吗?是否还有您无法解决的问题?
  • 嗯,重用位图是有道理的。
【解决方案2】:

您可以假设裁剪后的矩形永远不会大于完整图像的大小,分配它,然后记录一下您当前正在使用多少缓冲区。

或者,您可以拥有一个 grow 但从不缩小的数组,并且根据增长的粒度,您不会有太多的重新分配。

您可以查看MemoryStream.cs,了解他们如何处理容量变化。看EnsureCapacity(),如果我没看错的话,它只会在展开时分配一个新数组(数组在Capacity的setter中分配)。免责声明:我不确定这是否是 MemoryStream 的原始来源。

【讨论】:

  • array that you grow but never shrink - 是的,这正是我要找的。似乎 memoryStream 正是这样做的,但不能保证,所以我想知道是否已经有这样的类。此外,我需要在某处存储当前数据的长度。
  • 我正在查看 MemoryStream 反汇编的源代码并得出相同的结论
猜你喜欢
  • 2012-10-16
  • 1970-01-01
  • 2012-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-07
  • 1970-01-01
  • 2012-05-17
相关资源
最近更新 更多