2009-05-14 2 views
1

У меня есть то, что я предполагаю, это проблема фрагментации памяти.Фрагментация памяти WPF

Мы недавно перенесли наше приложение WinForms в приложение WPF. Есть некоторая обработка изображений, что это приложение делает, и эта обработка всегда работала в версии WinForms приложения. Мы переходим в WPF, и обработка умирает. Отладка в библиотеке имеет смерть в случайных точках, но всегда с массивом, который является нулевым, т. Е. Сбой распределения.

Сама обработка выполняется в библиотеке C++, вызванной p/invoke и достаточно интенсивной в памяти; если заданное изображение равно N x M пикселей, тогда изображение равно N x M x 2 байта (каждый пиксель без знака, и это изображение в оттенках серого). Во время обработки создаются пирамиды изображений, которые находятся в пространстве с плавающей точкой, поэтому общее использование памяти будет равно N x M x (2 + 2 + 4 + 4 + 4 + 4), где первые 2 являются входными, вторая 2 - выход, первый 4 - вход в поплавках, второй 4 - изображение разности уровней 0-го уровня, а последние две четверти - остальная часть пирамиды (поскольку они являются пирамидами, а каждый уровень равен половине размера в каждом направление, эти 4s являются верхними границами). Таким образом, для изображения 5000х6000 это 600 мб, которое должно вписываться в память просто отлично.

(Существует вероятность того, что использование маршаллинга увеличивает потребность в памяти другим N x M x 4, то есть входные и выходные изображения на стороне C#, а затем те же массивы, скопированные на сторону C++, - может быть, маршаллинг требование больше?)

Насколько фрагментирован WPF по сравнению с WinForms? Есть ли способ консолидировать память перед запуском этой обработки? Я подозреваю, что фрагментация является проблемой из-за случайного характера разломов, когда они происходят, и что это всегда проблема распределения памяти.

Или я должен полностью избегать этой проблемы, выполнив обработку как отдельный процесс, с передачей данных через сокеты или с подобной подобной вещью?

ответ

3

Если я прочитал это правильно, сбой памяти не происходит, а не с управляемой стороны. Кажется странным тогда обвинять WPF. Я понимаю, что вы делаете свое заключение на основании того, что «он работал в WinForms», но, скорее всего, больше изменений, чем просто это. Вы можете использовать такой инструмент, как .NET Memory Profiler, чтобы увидеть различия между тем, как приложение WPF и приложение WinForms обрабатывают память. Вы можете обнаружить, что ваше приложение делает то, чего вы не ожидаете. :)

За комментарий: Да, я понимаю. Если вы уверены, что вы исключили такие вещи, как изменения в окружающей среде, я думаю, вам нужно взять копию BoundsChecker и Memory Profiler (или DevPartner Studio) и вникнуть и посмотреть, что мешает вашему распределению памяти.

+0

Я перешел, что код обработки много раз. Если это утечка или плохое поведение, я просто не вижу этого; но перерывы определенно начали происходить, когда мы отправились в WPF из winforms. В противном случае код идентичен. – mmr

1

Я предполагаю, что GC перемещает вашу память. Попытайтесь зафиксировать память на неуправляемой земле, пока у вас есть необработанный указатель на массив, и отпустите ее как можно скорее. Возможно, WPF заставляет GC работать чаще, что объясняет, почему это происходит чаще с ним, и если это GC, то это объясняет, почему это происходит в случайных местах вашего кода.

Редактировать: Из любопытства вы также можете предварительно выделить всю свою память спереди (я не вижу код, поэтому не знаю, возможно ли это), и убедитесь, что все ваши указатели non-null, так что вы можете проверить, что это происходит в распределении памяти, а не какая-то другая проблема?

+0

pinning? DLL объявляет всю свою память нуля внутри себя. Если ГК блуждает по всему месту, то это действительно означало бы переход в другой процесс, чтобы избежать такого придирчивого поведения. – mmr

+0

Ну, это указатели на * gcnew * объекты или * новые * объекты? Я предполагал, что вы принимаете int * для необработанных пиксельных данных из класса Bitmap. GC может забрать растровое изображение и переместить его во время работы. – FryGuy

+0

Да, я этого не делаю. Я использую изображения DICOM, которые не являются растровыми изображениями. Визуализация выполняется как текстуры openGL, а сами изображения - просто массивы - в приложении C#, они являются пользователями, а в dll C++ они становятся float, чтобы иметь отрицательные значения и достаточный динамический диапазон. Итак, они предназначены для «новых» объектов. – mmr

0

Похоже, вы хотите быть более внимательными к управлению памятью в целом; т.е.: либо запустите движок обработки в отдельном адресном пространстве, которое тщательно управляет памятью, либо предварительно распределите достаточно большой фрагмент, прежде чем память будет слишком фрагментирована и будет управлять изображениями только в этой области. Если вы используете адресное пространство с помощью.NET в длительном процессе, и вам нужны большие смежные области, в какой-то момент это всегда будет потенциально терпеть неудачу. Просто мой 2c.

+0

Итак, в основном, просто перейдите ко второму процессу - это то, что я слышу. Почему это всегда потенциально терпит неудачу? Что здесь делает .NET, что делает его настолько неустойчивым? – mmr

Смежные вопросы