【问题标题】:WPF memory fragmentationWPF内存碎片
【发布时间】:2010-10-26 07:54:16
【问题描述】:

我认为是内存碎片问题。

我们最近将 WinForms 应用程序移植到 WPF 应用程序。此应用程序执行一些图像处理,并且此处理始终在应用程序的 WinForms 版本中工作。我们去WPF,处理死了。调试到库中会随机出现死亡,但总是有一个为空的数组,即分配失败。

处理本身是在一个由 p/invoke 调用的 C++ 库中完成的,并且内存相当密集;如果给定的图像是 N x M 像素大,则图像是 N x M x 2 字节大(每个像素都是无符号短,并且是灰度图像)。在处理过程中,图像金字塔在浮点空间中,因此总内存使用量将是 N x M x (2 + 2 + 4 + 4 + 4 + 4),其中第一个 2 是输入,第二个2 是输出,前 4 是浮点数的输入,第二个 4 是第 0 级差异图像,最后两个四是金字塔的其余部分(因为它们是金字塔,每个级别是每个级别的一半大小方向,这 4 个是上限)。因此,对于 5000x6000 的图像,这是 600 mb,应该可以很好地放入内存中。

(使用编组可能会增加另一个 N x M x 4 的内存需求,即 C# 端的输入和输出图像,然后将相同的数组复制到 C++ 端 - 编组要求更大?)

与 WinForms 相比,WPF 的碎片化程度如何?有没有办法在运行这个处理之前整合内存?我怀疑由于破损的随机性,当它们发生时,碎片是问题,而且它总是一个内存分配问题。

或者我应该通过使处理作为一个单独的进程运行,通过套接字或类似的东西传输数据来完全避免这个问题?

【问题讨论】:

    标签: c# c++ wpf memory fragmentation


    【解决方案1】:

    如果我没看错,内存分配失败发生在非托管端,而不是托管端。责怪WPF似乎很奇怪。我认识到您是基于“它在 WinForms 中工作”这一事实得出的结论,但可能还有更多的变化。您可以使用.NET Memory Profiler 之类的工具来查看 WPF 应用程序和 WinForms 应用程序处理内存的方式之间的差异。您可能会发现您的应用程序正在做一些您意想不到的事情。 :)

    每条评论:是的,我明白了。如果您确信您已经排除了诸如环境变化之类的事情,我认为您必须获取BoundsChecker 和 Memory Profiler(或DevPartner Studio)的副本并深入研究,看看是什么弄乱了您的内存分配。

    【讨论】:

    • 我已经检查了很多次处理代码。如果它泄漏或行为不端,我只是没有看到它;但是当我们从 winforms 转到 WPF 时,中断肯定开始发生。其他代码相同。
    【解决方案2】:

    我猜 GC 正在移动你的记忆。只要您有指向数组的原始指针,请尝试将内存固定在非托管土地上,并尽快取消固定。 WPF 可能导致 GC 运行得更频繁,这可以解释为什么它会更频繁地发生,如果是 GC,那么这可以解释为什么它会在代码中的随机位置发生。

    编辑:出于好奇,您是否还可以预先分配所有内存(我没有看到代码,所以不知道这是否可能),并确保您的所有指针都是非-null,所以你可以验证它实际上是在内存分配中发生的,而不是其他一些问题?

    【讨论】:

    • 固定? dll 在其内部声明其所有暂存内存。如果 GC 到处乱跑,那真的意味着要进入另一个进程,只是为了避免这种不稳定的行为。
    • 那么,指针是指向 gcnew 对象还是 new 对象?我假设您将 int* 从 Bitmap 类中提取到原始像素数据中。 GC 可以在您运行时拾取位图并移动它。
    • 是的,我不这样做。我正在使用不是位图的 DICOM 图像。可视化是作为 openGL 纹理完成的,图像本身只是数组——在 C# 应用程序中,它们是 ushorts,而在 C++ dll 中,它们变成浮点数,以便具有负值和足够的动态范围。因此,它们是“新”对象。
    【解决方案3】:

    听起来您一般要更加小心地管理内存;即:要么在单独的地址空间中运行处理引擎,该地址空间仔细管理内存,要么在内存变得过于碎片化之前预先分配足够大的块并仅管理该区域中的图像。如果您在一个长时间运行的进程中与 .NET 运行时共享地址空间,并且您需要大的连续区域,那么它总是会在某个时候失败。只是我的 2c。

    【讨论】:

    • 所以,基本上,我所听到的只是进入第二个过程。为什么它总是可能失败? .NET 在这里做了什么让它如此不稳定?
    【解决方案4】:
    猜你喜欢
    • 2013-08-14
    • 2018-09-25
    • 2012-12-11
    • 2011-01-17
    • 2020-02-15
    • 1970-01-01
    • 1970-01-01
    • 2020-08-21
    相关资源
    最近更新 更多