21

Снимок экрана: информация о системе из Process Explorer

Эта системная информация взята из Process Explorer. Физическая память все еще доступна, но система почти не показывает ОЗУ.

Диспетчер задач также показывает, что используется около 74% общего ОЗУ.

С момента установки Windows 8.1 на компьютере было 4+8 = 12 ГБ оперативной памяти. Я обновил его, изменив модуль 4 ГБ на 8 ГБ. Может ли это быть проблема? Или это нормальное поведение, и я просто неправильно понял значение доступной физической памяти?

1 ответ1

60

Короткий ответ

Всплывающее окно "Недостаточно памяти" говорит о том, что у вас исчерпан лимит частной выделенной памяти - тип виртуальной памяти. Не то, что у вас заканчивается ОЗУ (физическая память). Это не имеет значения , сколько свободной оперативной памяти у вас есть. Наличие большого количества доступной оперативной памяти не позволяет вам превысить предел фиксации. Предел фиксации - это сумма вашей общей оперативной памяти (используется ли она или нет!) плюс ваш текущий размер файла подкачки.

И наоборот, то, что "использует" лимит фиксации (которое главным образом является созданием частного виртуального адресного пространства процесса), не обязательно использует ОЗУ! Но ОС не допустит ее создания, если не знает, что есть место для ее хранения, если это когда-либо понадобится. Таким образом, вы можете столкнуться с лимитом фиксации без использования всей вашей оперативной памяти или даже большей части вашей оперативной памяти.

Вот почему вы не должны работать без файла подкачки. Обратите внимание, что файл подкачки может вообще не записываться! Но это все же позволит вам избежать ошибок "недостаточно памяти" и "недостаточно памяти".

Промежуточный ответ

На самом деле в Windows нет сообщения об ошибке нехватки оперативной памяти. То, что у вас заканчивается, это "предел коммитов".

График "Система" в этой версии Process Explorer имеет плохое имя. Он должен быть помечен как "совершить заряд". (В версии, которая у меня есть, она называется "System commit". Лучше, но все же не совсем соответствует.) В любом случае, "текущая" высота графика - это то, что показано ниже в текстовом разделе как "Commit Charge" - "Current", а максимальная высота графика представляет "Commit Charge" - "Limit".

"Зафиксировать плату" относится к виртуальному адресному пространству, которое поддерживается файлом подкачки (если он у вас есть) - иными словами, если он не может уместиться в ОЗУ, остальная часть помещается в файл подкачки. (Существуют другие типы vas, которые либо поддерживаются другими файлами - они называются "mapped" vas - или которые должны постоянно находиться в оперативной памяти; последний называется "nonpageable".) "Лимит коммита" - это максимум, который может быть "комиссионный сбор". Он равен размеру вашей оперативной памяти плюс размер файла подкачки.

У вас, очевидно, нет файла подкачки (я могу сказать, потому что ваш предел фиксации равен размеру ОЗУ), поэтому предел фиксации - это просто размер ОЗУ.

Видимо различные программы + ОС использовали почти все максимально возможное коммит.

Это не имеет прямого отношения к тому, сколько оперативной памяти свободно или доступно. Да, у вас есть около 4,5 ГБ оперативной памяти. Это не значит, что вы можете превысить лимит коммитов. Выделенная память не обязательно использует ОЗУ и не ограничена объемом доступной ОЗУ.

Вам нужно либо снова включить файл подкачки - используя этот многообещающий файл, я бы предложил файл подкачки объемом 16 ГБ, потому что вы не хотите заставлять ОС хранить столько памяти в ОЗУ, и файл подкачки работает лучше, если он имеет много свободного места - или добавить больше оперативной памяти. Намного больше. Для хорошей производительности у вас должно быть достаточно места в оперативной памяти для кода и других вещей, которые не поддерживаются файлом подкачки (но могут быть перенесены в другие файлы).

Очень длинный ответ

(но все же намного короче, чем глава по управлению памятью Windows Internals...)

Предположим, что программа выделяет 100 МБ приватной виртуальной памяти процесса. Это делается с помощью вызова VirtualAlloc с параметром commit. Это приведет к увеличению "фиксированного сбора" на 100 МБ. Но это "распределение" фактически не использует ОЗУ! ОЗУ используется только при первом обращении к некоторой части вновь созданного виртуального адресного пространства .

Как в конечном итоге ОЗУ используется

(если это когда-либо делает)

Первоначальный доступ к вновь зафиксированному пространству почти всегда был бы записью в память (чтение вновь выделенных закрытых vas перед записью почти всегда является ошибкой программирования, поскольку его начальное содержимое, строго говоря, не определено). Но читайте или пишите, в результате, когда вы в первый раз касаетесь страницы недавно выделенного vas, это ошибка страницы. Хотя слово "ошибка" звучит плохо, ошибки страницы являются полностью ожидаемым и даже обязательным событием в ОС виртуальной памяти.

В ответ на этот конкретный тип ошибки страницы пейджер (часть диспетчера памяти операционной системы, которую я иногда сокращаю как "Mm") будет:

  1. выделять физическую страницу оперативной памяти (в идеале из списка нулевых страниц, но в любом случае это происходит из того, что Windows называет "доступным": список нулевых, свободных или резервных страниц в том порядке предпочтений);
  2. заполните запись таблицы страниц, чтобы связать физическую страницу с виртуальной страницей; и наконец
  3. отклонить исключение ошибки страницы.

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

Мы говорим, что страница была "разбита" на рабочий набор процесса и в ОЗУ. В диспетчере задач это будет выглядеть как увеличение "частного рабочего набора" процесса на одну страницу (4 КБ). И сокращение доступной физической памяти на одну страницу. (Последнее может быть трудно заметить на загруженной машине.)

Примечание 1: эта ошибка страницы не связана с чтением с диска. Никогда ранее недоступная страница выделенной виртуальной памяти не начинает жизнь на диске; он не имеет места на диске , чтобы прочитать его с. Он просто "материализуется" на ранее доступной странице ОЗУ. Статистически, на самом деле, большинство сбоев страниц разрешаются в ОЗУ либо на общие страницы, которые уже находятся в ОЗУ для других процессов, либо в кэшах страниц - в резервных или измененных списках, либо в виде страниц с нулевым требованием, подобных этой.

Примечание 2: Это займет всего одну страницу, 4096 байт, из "Доступно". Целевое адресное пространство, которого никогда не трогали, обычно реализуется - с ошибками - только по одной странице за раз, так как каждая страница "касается" впервые. Не было бы никакого улучшения, никакого преимущества, делая больше одновременно; это займет всего n раз больше времени. В отличие от этого, когда страницы должны быть прочитаны с диска, предпринимается попытка "чтения", поскольку подавляющее большинство времени чтения с диска приходится на каждую операцию, а не на фактическую передачу данных. Сумма "совершено" остается на уровне 100 МБ; тот факт, что одна или несколько страниц были повреждены, не уменьшает плату за фиксацию.

Примечание 3: Предположим, у нас есть 4 ГБ "доступной" оперативной памяти. Это означает, что мы можем ссылаться на уже выделенную, но ранее не указанную фиксированную память еще миллион раз (4 ГБ / 4096), прежде чем у нас не будет ОЗУ. В этот момент, если у нас есть файл подкачки, как предполагали Дэвид Катлер и Лу Пераццоли, некоторые из страниц с самой давней давностью в ОЗУ будут сохранены на диске, а затем предоставлены для использования при устранении этих более недавних ошибок страниц. (На самом деле ОС будет инициировать методы восстановления ОЗУ, такие как "обрезка рабочего набора", а не до этого, а фактические записи в файл подкачки кэшируются и группируются в измененном списке страниц для эффективности, и и ... ) Ничто из этого не повлияет на количество "совершенных". Это относится, тем не менее, к "пределу коммитов". Если в оперативной памяти нет места для всей "выделенной" памяти, избыток можно сохранить в файле подкачки. Таким образом, размер файла подкачки вносит свой вклад в "ограничение на принятие".

И это продолжает происходить ...

Но давайте предположим, что мы еще не сделали эти миллионы ссылок, и до сих пор доступно около 4 ГБ страниц. Теперь давайте предположим, что тот же процесс - или другой, неважно - другой VirtualAlloc, на этот раз, скажем, выделено 200 МБ. Опять же, эти 200 МБ добавляются к комиссии за фиксацию и не удаляют ОЗУ из доступного. Простое адресное пространство VirtualAlloc не использует соответствующий объем ОЗУ, а наличие "доступной" ОЗУ с низким объемом не ограничивает объем адресного пространства, которое вы можете использовать в VirtualAlloc (равно как и наличие большого объема ОЗУ не увеличивает его).

(Хорошо, хорошо ... есть небольшая часть накладных расходов, равная одной (доступная для страницы!) страница, которая используется для таблицы страниц на каждые 2 МБ (4 МБ, если вы работаете в системе x86, не-PAE) виртуального адресного пространства, и имеется "дескриптор виртуального адреса" в несколько десятков байтов для каждого Выделен практически непрерывный диапазон.)

Таким образом, это возможно - и часто! - использовать много "фиксации заряда" при использовании только небольшого количества оперативной памяти.

Итак, если "фиксация" виртуального адресного пространства не использует ОЗУ, почему должен быть предел?

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

Когда Mm утверждает запрос VirtualAlloc, он обещает - "принятие обязательства" - что все последующие обращения к памяти в выделенной области будут успешными; они могут привести к сбоям страниц, но все эти ошибки можно будет устранить, поскольку в нем достаточно места для хранения содержимого всех этих страниц, будь то в ОЗУ или в файле подкачки. Mm знает об этом, потому что знает, сколько там места для хранения (предел фиксации) и сколько уже было "зафиксировано" (текущий заряд фиксации).

(Но все эти страницы еще не обязательно были доступны, поэтому не обязательно иметь фактический объем хранилища, чтобы соответствовать сумме, выделенной в любой момент времени.)

Так... А как насчет "системы не хватает памяти"?

Если вы попытаетесь использовать VirtualAlloc, и текущая плата за фиксацию плюс запрошенный размер выделения приведет к превышению лимита фиксации, а ОС не сможет развернуть файл подкачки для увеличения лимита фиксации ... вы получите всплывающее окно "недостаточно памяти" вверх, и процесс видит вызов VirtualAlloc FAIL. Большинство программ просто опустят руки и умрут в этот момент. Некоторые будут слепо нажимать, предполагая, что вызов выполнен успешно, и потерпят неудачу позже, когда они попытаются сослаться на регион, который, по их мнению, они выделили.

Еще раз (извините за повторение): не имеет значения, сколько у вас доступно ОЗУ. ОС пообещала, что ОЗУ или пространство подкачки будут доступны, когда это необходимо, но это обещание не вычитает из "Доступно". Доступная оперативная память используется коммитом vm только при первом обращении к нему, что и является причиной его сбоя ... т.е. реализуется в физической памяти. И просто выделение (= выделение) виртуальной памяти не делает этого. Он занимает только свободное виртуальное адресное пространство и выделяет из него полезное виртуальное адресное пространство.

Но в "из памяти" случае был запрос выделения для выделенной памяти, и ОС добавил ток фиксацию заряда до размера этого neew запроса ... и обнаружил , что общее больше , чем предел фиксации. Так что, если ОС одобрит этот новый, и после этого на все это пространство будет ссылаться, то не будет никаких реальных мест (RAM + pagefile) для хранения всего этого.

ОС не позволит этого. Это не позволит выделить больше сосудов, чем у него есть место, чтобы сохранить его в худшем случае - даже если все это "сломано". Это цель "предела коммитов".

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

Обратите внимание, что существует другой тип vas, называемый "mapped", который в основном используется для кода и для доступа к большим файлам данных, но он не взимается с платы за фиксацию и не ограничен "пределом фиксации". Это связано с тем, что он имеет свою собственную область хранения, файлы, которые "сопоставлены" с ней. Единственным ограничением для "сопоставленных" vas является количество дискового пространства, которое у вас есть для сопоставленных файлов, и количество свободных vas в вашем процессе для их сопоставления.

Но когда я смотрю на систему, я еще не совсем на пределе коммитов?

Это в основном проблема измерения и учета. Вы просматриваете систему после того, как вызов VirtualAlloc уже был опробован и не выполнен.

Предположим, у вас осталось всего 500 МБ, а какая-то программа пыталась использовать VirtualAlloc 600 МБ. Попытка не удалась. Затем вы смотрите на систему и говорите: «Что? Осталось еще 500 МБ!«На самом деле, может быть, к тому времени их останется гораздо больше, потому что к этому моменту рассматриваемый процесс, вероятно, полностью исчезнет, поэтому ВСЕ его ранее выделенная выделенная память была освобождена.

Беда в том , что вы не можете вернуться в прошлое и посмотреть , что коммит обвинение было в тот момент , была сделана попытка Alloc. И вы также не знаете, сколько места было для этой попытки. Таким образом, вы не можете окончательно увидеть, почему попытка не удалась, или сколько еще "предела коммитов" понадобилось бы, чтобы это сработало.

Я видел "системе не хватает памяти". Что это такое?

Если в приведенном выше случае ОС МОЖЕТ развернуть файл подкачки (то есть вы оставите для него значение по умолчанию "управляемая системой", или вы управляете им, но вы установили максимум больше исходного, И достаточно свободного места на диске), и такое расширение достаточно увеличивает предел фиксации, чтобы позволить вызову VirtualAlloc успешным образом, затем ... Mm расширяет файл подкачки, и вызов VirtualAlloc выполняется успешно.

И вот тогда вы видите, что "система работает НИЗКОЕ в памяти". Это раннее предупреждение о том, что если все будет продолжаться без смягчения, вы, скорее всего, вскоре увидите предупреждение "недостаточно памяти". Время закрывать некоторые приложения. Я бы начал с окон вашего браузера.

И ты думаешь, это хорошо? Расширение файла подкачки - зло !!!

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

Наконец, как только все процессы, которые "зафиксировали" пространство в расширении, завершили работу (при выключении ОС, если не раньше), экстенты будут автоматически освобождены, и файл подкачки вернется к своему предыдущему размеру и распределению - если он был смежным до этого, он это снова.

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

Но но НО...

Я читал на десятках веб-сайтов, что если вы разрешите расширение файла подкачки, Windows будет постоянно расширять и сжимать файл подкачки, и это приведет к фрагментации файла подкачки, пока вы не выполните его дефрагментацию.

Они просто не правы.

Если вы никогда не видели всплывающее окно "Недостаточно памяти" (или, в более старых версиях, "Недостаточно памяти"), ОС никогда не расширяла ваш файл подкачки.

Если вы видите это всплывающее окно, то это говорит о том, что ваш начальный размер файла подкачки слишком мал. (Я хотел бы установить его примерно в 4 раза выше максимального наблюдаемого использования; т. Е. Счетчик перфмонов "% pagefile use peak" должен быть меньше 25%. Причина: пространство подкачки управляется так же, как и любая другая куча, и лучше всего работает с большим количеством свободного места для игры.)

Но почему они просто ...

Кто-то может возразить, что ОС должна просто разрешить распределение, а затем дать сбоям ссылки, если не доступно ОЗУ для устранения ошибок страницы. Другими словами, выше, где мы описали, как работает ошибка начальной страницы, что делать, если "выделить доступную физическую страницу ОЗУ" (шаг 1) невозможно, потому что не было ни одной доступной, и не было места осталось на странице что-нибудь сделать доступным?

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

Философия проектирования заключается в том, что VirtualAlloc будет возвращать ноль (технически NULL-указатель) вместо адреса, если вы исчерпали предел фиксации, и вполне разумно ожидать, что программист узнает, что вызов VirtualAlloc может завершиться неудачно. Поэтому программисты должны проверять этот случай и делать что-то разумное в ответ (например, дать вам возможность сохранить свою работу до этого момента, а затем завершить программу "изящно"). (Программисты: вы проверяете, возвращается ли указатель NULL из malloc, new и т.д., Да? Тогда почему бы тебе не от этого?)

Но программисты не должны ожидать, что простая ссылка на память, как

i = 0;             // initialize loop counter

может произойти сбой - нет, если он находится в области успешно зафиксированного адресного пространства. (Или сопоставленное адресное пространство, в этом отношении.) Но это то, что могло бы произойти, если бы придерживалась философии «разрешить чрезмерное выделение ресурсов, пусть ссылка на память потерпит неудачу».

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

Это можно сделать ... Но обработчику было бы сложно знать, как "поступать правильно" в ответ на эти исключения, поскольку в коде было бы очень много точек, где они могут возникнуть. (В частности, они могут возникать при каждой ссылке на память на память VirtualAlloc, на память, выделенную с помощью malloc или new ... а также на все локальные переменные, поскольку стек тоже VirtualAlloc.)

Короче говоря, заставить программу изящно провалиться в этих случаях было бы очень сложно.

С другой стороны, довольно легко проверить, не возвращен ли указатель NULL из VirtualAlloc (или malloc или new, если на то пошло, хотя это не одно и то же), а затем сделать что-то разумное ... например, не пытаться идти и делать то, что было программой, для которой требуется это виртуальное пространство. И, возможно, спросите пользователя, хотят ли они сохранить свою работу до сих пор, если таковые имеются. (Конечно, слишком много приложений не удосуживаются сделать даже так много.)

Другие пользователи commit

Между прочим, "предел фиксации" не уменьшается из-за различных распределений ОС, таких как выгружаемый и невыгружаемый пул, список PFN и т. Д .; они просто заряжены, чтобы совершить обвинение, как они происходят. Кроме того, ни на коммит, ни на коммит не влияет размер видеопамяти или даже размера "окна" видеопамяти.

Проверь это сам

Вы можете продемонстрировать все это с помощью инструмента testlimit с сайта SysInternals. Опция -m выделит выделенное адресное пространство, но не "коснется" его, поэтому не вызовет выделение ОЗУ. Принимая во внимание, что опция -d будет выделять и также ссылаться на страницы, вызывая как увеличение комиссии за коммит, так и уменьшение доступной оперативной памяти.

Рекомендации

Windows Internals Руссиновича, Соломона и Ионеску. Есть даже демонстрации, позволяющие вам доказать все эти моменты с помощью инструмента testlimit. Тем не менее, я должен предупредить вас, что, если вы думаете, что это было долго, предупреждаем: одна только глава Mm - это 200 страниц; Выше очень упрощенная версия. (Пожалуйста, взгляните также на раздел "Благодарности" во Введении.)

Смотрите также документацию MSDN VirtualAlloc

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .