2012-07-02 2 views
3

Серверное приложение, в котором я работаю над построением с использованием C++ в Windows, заканчивается из-за нехватки памяти, когда виртуальный размер достигает где-то около 2 ГБ (32-разрядное приложение с включенным большим адресом). Однако я заметил, что Private Bytes значительно меньше. Текущая статистика:Виртуальный размер, вызывающий у программы нехватку памяти

Виртуальный Размер: 2,6 ГБ Private Bytes: 1,6 Гб

Разница в этих двух чисел составляет 1 ГБ. Итак, мои вопросы:

  1. Что представляет собой разница в 1 ГБ?
  2. Является ли мое приложение исчерпанием памяти из-за виртуального размера или частных байтов?

Я также запускаю свое приложение через утилиту VMMap и замечаю, что «частные данные» обычно на порядок превышают фиксированный размер. Другими словами, общий размер для частных данных может быть 200 МБ, но фиксированный размер составляет всего 20 МБ. Я не совсем уверен, что такое личные данные, но на основе моих исследований пока, похоже, указывает, что это всего лишь часть кучи.

EDIT:

Я искал утечки памяти с использованием Purify, но я на самом деле не нашел ничего полезного. Утечки памяти в виде памяти без указателей, похоже, не проблема, но утечка памяти с точки зрения слишком долго удерживаемой памяти может быть проблемой, я еще не изучил ее. Однако ключевым моментом является понимание того, почему виртуальный размер вызывает проблемы с памятью. Вопрос №1 является для меня самым важным для понимания этого.

+0

Возможно, у вас есть один или несколько утечек памяти, которые необходимо устранить? –

+0

Committed = память фактически используется приложением, private = память зарезервирована специально для приложения? И виртуальный размер = количество данных, выгружаемых на диск, я думаю. Я должен был бы вникать в это, чтобы точно знать. – JAB

+0

@JAB Это неверно. Я напишу ответ, объясняющий. – Polynomial

ответ

6

Это потребует небольшого объяснения, поэтому придерживайтесь меня здесь.

Прежде всего, эта тема представляет собой запутанную трясину противоречивых терминов, поэтому, пожалуйста, выбросьте все понятия, которые у вас есть «виртуальная память», что-то общее с дисками.

  • Физическая память - это память, хранящаяся на физическом устройстве. Это, как правило, относится к системной памяти, но также может быть дисковыми буферами, NIC буферов, видеокарта VRAM и т.п.
  • Виртуальная память представляет собой набор физических диапазонов адресов, отображенных в пользовательском режим (виртуальные) диапазоны адресов, так что доступ к памяти может быть обеспечен безопасным и раздельным образом.

Быстрое примечание о почему мы делаем это: если мы дали процессы прямые адреса памяти, мы могли бы только (посильнее) есть один магазин памяти. Это неудобно и плохо для производительности. Когда виртуальный адрес преобразуется в физический адрес вне диапазона системной памяти (ОЗУ), процессор выдает ошибку страницы. Это сигнализирует обработчик прерываний в ОС, который затем может делегировать операцию доступа к памяти на другое устройство. Полезно!

В 32-битной системе Windows максимальный объем виртуальной памяти, который может обрабатывать процесс в любой момент времени составляет 2 ГБ. Это можно увеличить до 3 ГБ, используя AWE, или 4 ГБ с /4GT и AWE. Это не означает, что процесс может только выделять 2 ГБ (или 3 ГБ/4 ГБ в зависимости от ранее обсуждавшихся настроек) памяти. Это просто означает, что он не может иметь одновременный доступ к большему, чем это.

Например, если вы открываете файл с памятью размером 1 ГБ, использование вашей виртуальной памяти увеличится на 1 ГБ. Вы не касаетесь ОЗУ и диска, но вы выделили блок виртуального адресного пространства для своего процесса. Если тогда вы захотите выделить 1,1 ГБ ОЗУ одновременно с наличием этого файла с отображением памяти, вы не сможете. Сначала вы должны отменить файл из своего процесса. Помните, что память все еще может быть выделена и заполнена данными, но на самом деле не отображена в вашем процессе. Если на вашем компьютере имеется 8 ГБ оперативной памяти, вы можете заполнить 6 ГБ данными и отобразить 2 ГБ в свой процесс. Когда вам нужно использовать другой раздел этой памяти, вы должны разблокировать существующий блок и отобразить другой раздел.

Таким образом, на разницу вы видите:

  1. Частные байт показывает, сколько байт памяти виртуального устройства ваш процесс отображенные, за исключением виртуальной памяти, разделяемой с другими процессами (например, файлы, отображенные, глобальные куча и т. д.).

  2. Рабочий набор сообщает вам, сколько байт физической памяти вы активно используете. Это включает в себя физическую память, буферы устройств и сопоставленные файлы. Это довольно странная фигура, так как она приравнивается к затрагиваемой физической памяти + отображаемой виртуальной несистемной памяти. В общем, вы должны полностью игнорировать эту цифру. Это практически бесполезно для отладки утечек памяти.

  3. Виртуальные байты - это общее количество виртуальной памяти, которую вы сопоставили.

Разница заключается в том, что вы сопоставили общий объем виртуальной памяти, например, кучу DLL-файлов или блок глобальной кучи, в процесс. Разница указывает, что общий размер этих общих сопоставлений составляет примерно 1 ГБ.

Имейте в виду, что ни это имеет ничего делать с свопинга, что передача страниц системной памяти на диск (так называемый «Pagefile»), чтобы увеличить доступность быстро системных ресурсов (ОЗУ). Именование этого файла не закончило путаницы в этой области Windows, и я буду в восторге, когда Microsoft, наконец, решит назвать его «своп», а не «виртуальной памятью» или «файлом страницы».

+0

О, и * определенно * дайте это прочитать: http://blogs.technet.com/b/markrussinovich/archive/2008/11/17/3155406.aspx Марк Руссинович - «da bawss» этой низкоуровневой памяти вещи. – Polynomial

+0

«Это может быть увеличено до 3 ГБ с использованием PAE».Фактически PAE позволяет 32-разрядным операционным системам получать доступ к более чем 4 ГБ памяти _physical_. AWE - это то, что позволяет 32-битным процессам получать доступ к более чем 2 ГБ (или 3 ГБ с 4 ГБ) пользовательской памяти с использованием окон памяти. 4GT - это то, что позволяет приложениям иметь до 3 ГБ сопоставленной памяти в пользовательской части виртуального адресного пространства. –

+0

Извините, я перепутал терминологию. Редактирование для исправления. – Polynomial

2
  1. Виртуальный Размер против Байт объяснил: What is private bytes, virtual bytes, working set? (см цитату ниже)
  2. Ваше приложение может ударить виртуальный предел размера в 2 ГБ, особ. так как вы видите такое поведение сами
  3. /LARGEADDRESSAWARE расширяет виртуальный предел размера для вашего приложения в Win32 операционных систем только тогда, когда сама система загружается с /3GB AKA 4GT включен

Virtual Bytes являются общее виртуальное адресное пространство, занимаемое весь процесс. Это похоже на рабочий набор, в том смысле, что он включает в себя файлы с отображением памяти (общие библиотеки DLL), но также включает в себя данные в резервном списке и данные, которые уже выгружены и находятся в , сидя в файле подкачки на диске где-то. Все виртуальные байты, используемые каждым процессом в системе с большой нагрузкой, будут содержать до значительно больше памяти, чем на самом деле.

Так отношения:

  • Private Bytes то, что приложение действительно выделяется, но включают в себя использование файла подкачки;
  • Рабочий набор - это незашифрованные частные байты плюс файлы с отображением памяти;
  • Виртуальные байты - это рабочий набор плюс выложенные частные байты и резервный список.
+0

Я прочитал ответ, который вы связывали больше раз, чем я помню, но я все еще смущен. Я хочу точно знать, почему цифры настолько разные, но я даже не могу их определить, если я точно не знаю, что может вызвать разницу. Итак, это данные в резервном списке и/или страницах, сидящих на диске? Если это так, почему Windows не избавляется от неиспользуемых страниц (тем самым уменьшая виртуальный размер), а не просто отказываясь? –

+0

Простая вещь для стартеров: Private Bytes рассчитывает на 'new' и' malloc' - по мере их достижения есть допустимый указатель на выделенную память и, следовательно, они занимают адресное пространство. Однако у вас есть весь код, который также отображается в адресное пространство, а не только ваши, но все эти DLL-библиотеки, все они имеют свои адреса. И они не являются частными байтами. Поэтому, если вы откроете Process Explorer или Visual Studio, панель «Модули» - вы увидите, сколько модулей загружено в процесс, и все они учитывают разницу, о которой вы просили. –

0

Только комментарий. Включение значка большого адреса сигнализирует ОС только о том, что он может безопасно делить виртуальное адресное пространство процессов, созданных из этого конкретного исполняемого файла, в режиме 3: 1 вместо обычных 2: 2. Существуют различные причины того, почему приложение должно явно идентифицировать, что оно поддерживает разделение 3: 1, но наиболее очевидным является то, что в режиме проверки 2: 2 MSB виртуального адреса может быть использован для проверки того, принадлежит ли адрес части ядра виртуального адресного пространства или части пользователя. В 3: 1 этот тест больше недействителен, так как MSB также является 1 для 1/3 части пользовательского пространства виртуального адресного пространства. Это требует, чтобы драйверы, которые это приложение может вызвать, также должны знать о возможном разделении 3: 1 и должны использовать другой метод для проверки того, принадлежит ли данный виртуальный адрес к пользовательскому пространству.

Вы все же должны явно указать ядру, чтобы включить поддержку пространственного разделения 3: 1 VA, как указал Р. Р..

+0

Просто имейте в виду, что/3GB вызывает проблемы с буфером обмена на больших разрешениях экрана с небольшим количеством ОЗУ. Печатный экран не будет помещаться в буфер буфера обмена ядра, поэтому операция завершится с ошибкой. Странность! – Polynomial

0

У меня была аналогичная проблема на моей машине, где приложение win32 для C/C++ /. NET закончилось из памяти. Он потреблял все 2 ГБ виртуальных адресов. Это выглядело как «Исчерпывание виртуальных адресов», потому что Process Explorer показал только около 900 МБ памяти, взятых приложением. VMMap показал 1,6 Гбайт частных данных и около 700 МБ незафиксированной памяти.

Причина была более чем простой. Приложение Verifier (C: \ Windows \ SysWOW64 \ appverif.exe), которое было настроено для тестирования приложения (основные тесты были отмечены - vfbasics.dll). После удаления приложения из Application Verifier он работал нормально.

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