Что использует так много незафиксированных «личных данных»? на Windows Server 2003?

Итак, у меня есть нативное приложение C ++, и оно должно отслеживать множество вещей в течение длительных периодов времени. Недостаточно памяти, когда диспетчер задач говорит, что процесс достигает где-то между 800 и 1200 МБ памяти, когда предел должен быть около 2 ГБ.

Я наконец понял, что происходит, когда я запустил VMMap против моего процесса, но это только дало мне больше вопросов. Что я обнаружил:

  • Общий размер (тип: итого, столбец: размер) много больше, чем то, о чем сообщали менеджер задач / проводник процессов
  • Общий размер, по-видимому, равен значению, которое не может превышать 2 ГБ, прежде чем моей программе не хватит памяти
  • Неопределенность использования памяти почти полностью вызвана «частными данными» — «размер» гораздо больше, чем «зафиксировано». Я видел случаи, когда было около 800 МБ подтвержденных личных данных, но «Размер» составлял около 1700 МБ.
  • Самые большие блоки «Частных данных» в основном состоят из набора пар из одного небольшого субблока (обычно между 4K и 16K), который имеет защиту «чтение / запись» и полностью зафиксирован, и одного большего субблока (между 90K и 400K), которая имеет «Зарезервированную» защиту и не совершена. Это похоже на огромную трату ресурсов. И обычно есть один большой (много мегабайт) подблок в конце, который «зарезервирован» и не зафиксирован.
  • У маленькой части пары обычно есть строки, которые я распознаю, в то время как у большего блока вообще нет строк.

Пример этих пар субблоков: (не мое приложение, но идея та же)
http://www.flickr.com/photos/95123032@N00/5280550393

Кажется, что, когда один блок приватных данных полностью фиксируется, выделяется новый блок (обычно такой же или в два раза больше предыдущего). Звучит справедливо. Тем не менее, я видел 3 блока, каждый размером более 100 МБ и менее 30 МБ. Мое приложение не должно вести себя так (т. Е. Использовать 400 МБ, а затем уменьшить на 300 МБ в течение нескольких часов), что это было бы возможно.

Насколько я могу судить, «Размер» — это фактический объем адресного пространства виртуальной памяти, который был выделен. «Committed» — это количество «Size», которое фактически используется (то есть через вызовы new / malloc). Если это действительно так, то почему существует такая огромная несоответствие между Size и Commited? И почему он выделяет блоки размером несколько сотен мегабайт?

Несколько странно то, что при работе в Windows 7 поведение совершенно иное. В то время как на 2003 Server приложение использует личные данные, в Windows 7 — Heap. Так … почему? Почему VMMap показывает в основном использование личных данных в 2003 году, но в основном использование кучи в 7? Какая разница? Ну, одно отличие состоит в том, что я не могу использовать кнопку «Распределение кучи …» в VMMap, чтобы увидеть, где размещаются все эти частные данные.

Я начинал задаваться вопросом, не вызывало ли это чрезмерное использование std :: string, так как строки, которые я распознал в парах (упомянутых выше), в основном состояли из строк, хранящихся в std :: string, которые часто создавались и уничтожались (подразумевая много распределения / освобождения памяти). Я преобразовал все, что мог, чтобы использовать массивы символов или память из пула памяти, но это, похоже, не дало результата. Все другие мои новые / часто удаляемые объекты уже имеют свои собственные пулы памяти.

Я также узнал о низкой куче фрагментации, поэтому я попытался включить это, но это также не имело значения. Я думаю, это потому, что Windows 2003 на самом деле не использует кучу. VMMap показывает, что куча с низкой фрагментацией включена, но поскольку она на самом деле не используется (то есть вместо этого она использует личные данные), на самом деле это не имеет значения.

На самом деле кажется, что эти пары субблоков фрагментируют большие блоки Private Data, что заставляет ОС выделять новые блоки. В конце концов, фрагментация становится настолько плохой, что, несмотря на то, что есть много свободного места, ни один из них, кажется, не может быть использован, и процессу не хватает памяти.

Итак, мои вопросы:

  1. Почему Windows Server 2003 использует личные данные вместо кучи? Это имеет значение?
    Есть ли способ заставить Windows Server 2003 использовать память кучи вместо?
    Если так, это улучшит мою ситуацию вообще?
  2. Есть ли способ контролировать распределение личных данных распределителем памяти ОС?
  3. Можно ли создать свою собственную пользовательскую кучу и выделить из нее (не изменяя большую часть моей кодовой базы), и может ли это улучшить мою ситуацию? Я знаю, что можно создавать пользовательские кучи, но, насколько я могу судить, вам нужно явно выделять из пользовательской кучи вместо того, чтобы просто вызывать новый или просто использовать контейнеры STL в обычном режиме.
  4. Я что-то пропустил или стоило бы попробовать?

3

Решение

Частные данные — это всего лишь классификация всей памяти, которая не распределяется между двумя или более процессами. Куча, перемещенные dll-страницы, стеки всех потоков в процессе, файлы с общей памятью и т. Д. Попадают в категорию личных данных.

ОС не сможет выполнить запрос памяти у процесса (через VirtualAlloc), если выполняется одно из условий,

  1. Непрерывное виртуальное адресное пространство (не память) недоступно для хранения запрошенного размера.
  2. Плата за фиксацию — общая память, выделенная для всего процесса и операционной системы, — достигла своего верхнего предела (это ОЗУ + размер файла подкачки)

Помимо этого выделение кучи может произойти сбой по своим собственным причинам, например, во время расширения они будут фактически пытаться получить больше памяти, чем размер запроса на выделение, который вызвал расширение — и если это не удается, они могут просто потерпеть неудачу — хотя фактический запрошенный размер может быть доступным через VirtualAlloc.

Мало что может накопить память,

  1. Имея много кучи — они заполонят память — потому что они держат больше в запасе. Много кучи означает, что много зарезервированного пространства, вероятно, останется неиспользованным. Сжатие кучи может помочь.
  2. Контейнеры STL, такие как vector и map, могут не сжиматься после удаления из них элементов. Сжатие их тоже может помочь.
  3. Такие библиотеки, как COM, выполняют некоторое кеширование и, таким образом, накапливают память — это может помочь исследовать отдельные библиотеки, чтобы узнать об их привычках захвата памяти.
3

Другие решения

когда диспетчер задач говорит, что процесс достигает где-то между 800 и 1200 МБ памяти, когда ограничение должно быть около 2 ГБ

Вероятно, вы смотрите на «Рабочий набор» в диспетчере задач, в то время как ограничение 2 ГБ для виртуальной памяти. Диспетчер задач не показывает количество зарезервированных виртуальных машин; он покажет совершенную сумму.

«Committed» — это количество «Size», которое фактически используется (то есть через вызовы new / malloc).

Нет, «Принятый» означает, что вы действительно коснулись страницы (то есть пошли по адресу и выполнили операцию загрузки или сохранения).

1. Почему Windows Server 2003 использует личные данные вместо кучи?

Согласно «Справочнику администратора Windows Sysinternals» Марка Руссиновича и Аарона Маргосиса:

Память личных данных — это память, выделенная VirtualAlloc и
это больше не обрабатывается диспетчером кучи или средой выполнения .Net

Таким образом, либо ваша программа по-разному управляет своей памятью в двух ОС, либо VMmap не может определить способ управления этой памятью как кучу в Windows Server 2003.

4. Есть ли что-то, что я пропускаю или стоило бы попробовать?

Вы можете работать с ограничением 3 ГБ в 32-разрядной ОС и 4 ГБ для 32-разрядных процессов в 64-разрядной ОС. Google для «/ 3G» и «/ 4G».

Отличным источником информации о подобных вещах является книга Марка Руссиновича, Дэвида Соломона и Алекса Ионеску «Windows Internals 6th Edition».

0

Я сталкиваюсь с той же проблемой.

В Windows 2003 мое приложение вызывает исключение нехватки памяти в модуле C ++ / CLI при попытке выделить массив размером 22 МБ с помощью gcnew. Тот же процесс отлично работает в Windows 7.

VMMap показывает, что запись «личных данных» в win2003 составляет почти 2 ГБ. После того, как я включил / 3GB флаг, эта запись также увеличилась почти до 3GB. Запись «куча» составляет около 14 МБ, а «управляемая куча» — ничто!

В windows 7 «личные данные» составляют всего 62 МБ, «куча» — 316 МБ, а «управляемая куча» — 397 МБ. Полное использование памяти намного меньше чем win2003.

0
По вопросам рекламы [email protected]