2012-06-06 2 views
10

Я читал о памяти пределисключение памяти 1.2GB

У меня есть приложение, которое работает с огромными изображениями, которые необходимо загружать. Как в обработке видео с одиночными кадрами. Приложение имеет около 40 плагинов, каждый из которых может содержать базу данных, обработку изображений и графический интерфейс WPF.

Приложение также имеет 2 плагина, которые используют более старые DotNet Winforms.

Все работает хорошо, за исключением того, что приложение занимает около 1,2 ГБ в ОЗУ. Затем в необычных местах в плагинах, где выделена новая память, я получаю «Исключение из памяти».

Я работаю над системой 64Bit, составленной как 32Bit. Я больше не знаю, что делать и как искать любую ошибку.

Есть ли предел, или я могу их поймать?

+0

так сколько пользователей вам нужно для достижения предела? – Limey

+0

Я не понимаю вопроса. Изображения 1500x1500 пикселей, и все работает хорошо. С тем же кодом и теми же процедурами, если исходное разрешение изображения видеопотока составляет 3500x3500, тогда приложение вылетает с исключением памяти. Но компьютер имеет более 3 ГБ больше оперативной памяти и бесплатно. – Nasenbaer

+1

Я бы пошел на профайлер _memory_ (т. Е. Не профилировщик _performance_), например [ANTI Memory Profiler] (http://www.red-gate.com/products/dotnet-development/ants-memory-profiler/). –

ответ

19

Очень сложно написать 32-разрядную программу, которая потребляет всего доступного пространства виртуальной памяти. Вы попадете в стену значительно ниже 2 гигабайт, то, что у вас заканчивается, - это кусок виртуальной памяти, достаточно большой, чтобы соответствовать требуемому размеру. Вы можете подняться до предела 2 ГБ, сделав небольшие выделения, достаточно маленькие, чтобы вписаться в отверстия.

Эта стена поражает в начале программы, которая управляет растровыми изображениями. Они могут потреблять большой кусок виртуальной машины для хранения растровых пикселей, и это должно быть смежным распределением. Они хранятся в array, а не tree. Это неуправляемое распределение памяти, типичные профили памяти .NET, как правило, немного беспомощны, чтобы показать вам проблему.

Существует не что-то разумное, что вы можете сделать для фрагментации пространственного пространства, то понятие о том, что потребление всей доступной виртуальной машины должно быть возможно, просто неверно. Вы можете получить больше пространства для передышки в 64-разрядной операционной системе, запустив editbin.exe в post build event и воспользуйтесь опцией командной строки /LARGEADDRESSAWARE. Это позволяет процессу использовать доступные 4 гигабайта виртуальной машины, вариант, характерный для 64-разрядной версии Windows, и возможно, потому что Windows не нуждается в верхних 2 ГБ. И, конечно же, изменение целевой платформы в AnyCPU - это быстрый и простой способ получить кучу виртуальной памяти.

0

Приложение 32Bit, работающее на окнах (даже если ОС 64Bit) имеет 4Gb адресное пространство, но оно разделено на 2Gb Application/2Gb System (это можно изменить на 3/1 с помощью другого переключателя запуска).

Весьма вероятно, что общая память, которую вы используете, на самом деле составляет 2 ГБ, а не 1,2 ГБ, как вы определяете эту фигуру в 1,2 ГБ. Вы посмотрели приложение, используя инструмент process explorer?

Если вы изменили приложение на ANYCPU или 64Bit, вы должны обнаружить, что это ограничение исчезает (хорошо перемещается в более крупное значение) на 64-битной ОС.

+7

Добавить информацию. 2GB для неуправляемых приложений. Для управляемых приложений OOM происходит примерно на 1,2-1,5 ГБ примерно из-за GC. изменение на 64 бит может решить проблему, но может быть невозможно, если какая-либо из зависимостей составляет только 32 бит. –

0

Чтобы стать более детерминированным, вы должны написать некоторые интеграционные тесты, чтобы проверить, где находится ваша память. Вы можете сделать это сейчас с WMemoryProfiler.Я бы сначала загрузил изображения размером 1500x1500, очистил все, а затем отметьте все объекты, как известно. Затем я переместил большие изображения и проверил, какие новые объекты были выделены, и посмотрим, сколько из них есть и кто их владеет.

Вы говорите, что есть много внешних модулей. Возможно, вам стоит отказаться от некоторых из них из-за неразумного использования памяти и заменить их чем-то лучшим. Теперь вы можете проверить.

Если вы достигли предела, вы все равно можете выгрузить некоторые изображения и загрузить их по требованию, если вы и ваши плагины поддерживаете ленивые структуры, такие как IEnumerable<Image>, где вы, как поставщик, можете решить, когда загружать изображения и как долго их хранить в кеш, пока вы не избавитесь от ссылки, чтобы освободить память.

[Test] 
public void InstanceTracking() 
{ 
    using (var dumper = new MemoryDumper()) // if you have problems use to see the debugger windows true,true)) 
    { 
     TestWith1500x1500(); 
     dumper.MarkCurrentObjects(); 
     TestWith3000x3000(); 
     ILookup<Type, object> newObjects = dumper.GetNewObjects() 
               .ToLookup(x => x.GetType()); 

     // here we do find out which objects are holding most of the memory 
     MemoryStatistics statOld = dumper.GetMemoryStatistics(); 
     foreach (var typeInfo in statOld.ManagedHeapStats 
            .OrderByDescending(x => x.Value.Count)) 
     { 
      Console.WriteLine("Type {0} has {1} instances of total size {2:N0} bytes", 
          typeInfo.Key, 
          typeInfo.Value.Count, 
          typeInfo.Value.TotalSize); 
     } 

     // then check with the info from above who is holding the most interesting new objects. 
     Console.WriteLine("New Strings:"); // just an example perhaps you should have a look at the images. 
     foreach (var newStr in newObjects[typeof(string)]) 
     { 
      Console.WriteLine("Str: {0}", newStr); 
     } 
    } 
} 
Смежные вопросы