WPF内存碎片

发布于 07-19 05:05 字数 753 浏览 9 评论 0 原文

我认为是内存碎片问题。

我们最近将 WinForms 应用程序移植到 WPF 应用程序。 此应用程序执行一些图像处理,并且此处理始终在应用程序的 WinForms 版本中运行。 我们转到 WPF,然后处理就结束了。 调试到库中会在随机位置发生死亡,但总是有一个数组为空,即分配失败。

处理本身是在 ap/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 是金字塔的其余部分(因为它们是金字塔,每个级别的大小是每个级别的一半)方向,这些 4 是上限)。 因此,对于 5000x6000 的图像来说,大小为 600 mb,应该可以很好地装入内存。

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

与 WinForms 相比,WPF 的碎片化程度如何? 有没有办法在运行此处理之前整合内存? 我怀疑碎片是问题所在,因为碎片发生时具有随机性,而且它始终是内存分配问题。

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

I've got what I assume is a memory fragmentation issue.

We've recently ported our WinForms application to a WPF application. There's some image processing that this application does, and this processing always worked in the WinForms version of the app. We go to WPF, and the processing dies. Debugging into the library has the death at random spots, but always with an array that's nulled, ie, allocation failed.

The processing itself is done in a C++ library called by a p/invoke and is fairly memory intense; if the given image is N x M pixels big, then the image is N x M x 2 bytes big (each pixel is an unsigned short, and it's a greyscale image). During the processing, image pyramids are made, which are in float space, so the total memory usage will be N x M x (2 + 2 + 4 + 4 + 4 + 4), where the first 2 is the input, the second 2 is the output, the first 4 is the input in floats, the second 4 is the 0th level difference image, and the last two fours are the rest of the pyramid (since they're pyramids and each level is half the size in each direction, these 4s are upper bounds). So, for a 5000x6000 image, that's 600 mb, which should fit into memory just fine.

(There's the possibility that using marshalling is increasing the memory requirement by another N x M x 4, ie, the input and output images on the C# side and then the same arrays copied to the C++ side-- could the marshalling requirement be bigger?)

How fragmented is WPF compared to WinForms? Is there a way to consolidate memory before running this processing? I suspect that fragmentation is the issue due to the random nature of the breakages, when they happen, and that it's always a memory allocation problem.

Or should I avoid this problem entirely by making the processing run as a separate process, with data transfer via sockets or some such similar thing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

旧竹 2024-07-26 05:05:36

如果我正确地理解了这一点,则内存分配失败发生在非托管端,而不是托管端。 那么归咎于 WPF 似乎很奇怪。 我认识到您是根据“它在 WinForms 中有效”这一事实得出的结论,但可能还有更多的变化。 您可以使用 .NET Memory Profiler 等工具来查看 WPF 应用程序和 WinForms 应用程序之间的差异治疗记忆。 您可能会发现您的应用程序正在执行您意想不到的操作。 :)

每条评论:是的,我明白。 如果您确信自己已经排除了环境变化等问题,我认为您必须获取 "="">BoundsChecker 和内存分析器(或 DevPartner Studio)并深入研究并查看是什么扰乱了您的内存分配。

If I read this correctly, the memory allocation failure is happening on the non-managed side, not the managed side. It seems strange then to blame WPF. I recognize that you are drawing your conclusion based on the fact that "it worked in WinForms", but there are likely more changes than just that. You can use a tool like the .NET Memory Profiler to see the differences between how the WPF application and the WinForms application are treating memory. You might find that your application is doing something you don't expect. :)

Per comment: Yup, I understand. If you're confident that you've ruled out things like environment changes, I think you have to grab a copy of BoundsChecker and Memory Profiler (or DevPartner Studio) and dig in and see what's messing up your memory allocation.

娇柔作态 2024-07-26 05:05:36

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

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

I'm guessing that the GC is moving your memory. Try pinning the memory in unmanaged land as long as you have a raw pointer to the array, and unpin it as soon as possible. It's possible that WPF causes the GC to run more often, which would explain why it happens more often with it, and if it's the GC, then that would explain why it happens at random places in your code.

Edit: Out of curiosity, could you also pre-allocate all of your memory up front (I don't see the code, so don't know if this is possible), and make sure all of your pointers are non-null, so you can verify that it's actually happening in the memory allocation, rather than some other problem?

野生奥特曼 2024-07-26 05:05:36

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

It sounds like you want to be more careful about your memory management in general; ie: either run the processing engine in a separate address space which carefully manages memory, or pre-allocate a sufficiently large chunk before memory gets too fragmented and manage images in that area only. If you're sharing address space with the .NET runtime in a long-running process, and you need large contiguous areas, it's always going to potentially fail at some point. Just my 2c.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文