Вызывается специальная область памяти, в которой могут временно храниться объекты Windows

Обновлено: 21.11.2024

Версию этой статьи для Microsoft Word 97 см. в разделе 89247.

Обзор

В этой статье объясняется, когда, где и как Microsoft Word для Windows создает временные файлы.

Дополнительная информация

Определение временного файла

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

Почему Word создает временные файлы?

Скорость

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

Целостность данных

Word использует временные файлы в качестве «страховочной сети» для защиты от системных ошибок в своей схеме сохранения файлов. Сохраняя сначала во временный файл, а затем переименовывая файл в правильное имя, Word обеспечивает целостность данных вашего исходного файла от проблем (таких как сбой питания или потеря сетевого подключения), которые могут возникнуть во время записи файла.< /p>

Типы временных файлов

Файл для MS-DOS

Это стандартные файлы MS-DOS.

Файл на основе файла документа

Разница между этим файлом и традиционным файлом MS-DOS заключается в том, что несколько программ могут читать и записывать эти файлы без ведома первоначального владельца. Кроме того, файлы документов имеют неотъемлемые свойства, которые позволяют Word создавать файлы и каталоги внутри файлов. При запуске Word создает один временный (прямой) файл документа с именем ~wrfxxxx.tmp. Вы можете определить, что это файл документа, поскольку начальный размер составляет 1536 байт. Этот временный файл документа используется для хранения всех объектов OLE, принадлежащих безымянным документам, отмене, буферу обмена и документам, исходные форматы которых не являются форматом документа (например, документы .txt, .rtf и Word 2.0). Word может открывать файлы документов, используя два разных режима: транзакционный и прямой. Эти режимы обсуждаются далее в этой статье.

Файлы транзакционных документов

Транзакционные файлы позволяют Word открывать файл, выполнять в него запись и заставлять другие программы, такие как Microsoft Excel, выполнять запись в него, но при этом сохраняется право восстановить файл до состояния, в котором он находился при первом запуске Word. открыл его.

Для этого файл документа создает фантомные изображения (обычно ~dftxxxx.tmp) всех изменений, внесенных в файл после его открытия; если Word сохраняет все изменения, содержимое ~dftxxxx.tmp объединяется с исходным файлом, а затем сохраняет его полную версию. И наоборот, если Word отменяет все изменения, файл ~dftxxxx.tmp удаляется, а исходный файл не изменяется. Word открывает все собственные файлы Word, используя файлы транзакций, которые создают фантомные изображения в каталоге Temp. При запуске Word файл Normal.dot обычно открывается в режиме транзакций, и для него создается файл-призрак с именем dftxxxx.tmp. FastSave, например, объединяет эти два файла при сохранении.

Прямой

Word использует прямое сохранение при открытии файла временного документа и при выполнении операции «Сохранить как» или полного сохранения (сохранение без быстрого сохранения). Файлы этого типа потребляют мало памяти (если вообще потребляют) и не создают фантомное изображение при создании или открытии.

Определенные файлы, создаваемые Word

В следующих таблицах перечислены некоторые временные файлы, которые создает Word.
Файлы, обычно создаваемые при запуске Word Имя файла
------------------------------------------------ ---------------------------------------
Файл для MS-DOS ( для резервирования 4 файловых дескрипторов) 0 байт ~wrf0000.tmp
рабочий файл на базе MS-DOS 0 байт ~mfxxxx.tmp
составной файл — транзакция 0 байт ~dftxxxx.tmp
составной файл — direct 1536 байт ~wrf0001.tmp
(безымянные файлы, отличные от Word/OLE)


Файлы восстановления Word Имя файла
------------------------------------------------- -------------------------------------
Временный файл для автовосстановления ~wraxxxx.tmp < br />AutoRecovery Автовосстановление сохранения .asd

Другие временные файлы Word Имя файла
--------- ----------------------------------
Копия другого документа ~wrcxxxx.tmp
Документ Word ~wrdxxxx.tmp
Временный файл документа ~wrfxxxx.tmp
Словарь ~wrixxxx.tmp
Буфер обмена ~wrlxxxx.tmp
Макрос ~wrmxxxx.tmp
Документ Word OLE ~wroxxxx.tmp
Скретч-файл ~wrsxxxx.tmp < br />Преобразованный (чужой) документ ~wrvxxxx.tmp

Упрощенный вид схемы, используемой для сохранения редактируемого файла

Word значительно повышает производительность, помещая временный файл в тот же каталог, что и сохраненный файл. Если бы Word поместил временный файл в другое место, ему пришлось бы использовать команду MS-DOS COPY, чтобы переместить временный файл из другого каталога в сохраненное место. Оставив временный файл в том же каталоге, что и сохраненный файл документа, Word может использовать команду MS-DOS MOVE, чтобы быстро назначить временный файл сохраненным документом.

Когда и где Word создает временные файлы

Расположение, в котором Word создает временные файлы, является жестко заданной информацией и не может быть изменено. Поэтому важно, чтобы разрешения NTFS для пользователя были установлены соответствующим образом. Для получения дополнительной информации щелкните следующий номер статьи, чтобы просмотреть статью в базе знаний Майкрософт:

277867 Разрешения Windows NTFS требуются при запуске Word в любом разделе NTFS, на котором установлена ​​Windows 2000, Windows XP Professional, Windows Server 2003 или Windows Vista

Как правило, Word создает временные файлы для следующих типов данных.

Встроенные объекты Word (временный каталог)

Когда Word действует как серверная программа OLE, встроенные объекты Word сохраняются как временные файлы в каталоге Temp.

OLE 2.0 требует дополнительного места на диске. Когда вы запускаете программы OLE, Word должен предоставить копии данных на сервер. Широкое использование OLE 2.0 в одном сеансе программы нередко приводит к накоплению большого объема временной памяти на жестком диске.

Временный файл (временный каталог)

Когда в Word заканчивается внутренняя оперативная память (ОЗУ), он всегда создает один временный рабочий файл в каталоге Temp для хранения информации. Этот рабочий файл содержит информацию, которая выгружается из внутреннего файлового кэша Word, выделенного из глобальной системной памяти. Размер рабочего файла варьируется от 64 килобайт (КБ) до 3,5 мегабайт (МБ).

Размер кэша по умолчанию в Word составляет 64 КБ.

Для получения дополнительных сведений о том, как увеличить размер кэша в Word, щелкните следующий номер статьи базы знаний Майкрософт:

212242 Где в реестре хранятся настройки для Word 2000

Записанный макрос (временный каталог)

При записи макроса Word создает временный файл в папке Temp Windows.

Преобразованные файлы (временный каталог)

Преобразователи текстового процессора, поставляемые с Word, создают временные файлы в формате Rich Text Format (RTF), которые Word использует для доступа к определенным преобразователям.

Заблокированные файлы (временный каталог)

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

Сохраненные файлы (тот же каталог, что и сохраненный файл)

При нажатии кнопки "Сохранить" в меню "Файл" происходит следующее:

Word создает новый временный файл, используя отредактированную версию документа.

После того как Word создаст временный файл, Word удалит предыдущую версию документа.

Word переименовывает временный файл в то же имя, что и предыдущая версия документа.

Текст, вставленный между файлами (тот же каталог, что и исходный файл):


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

Файл владельца (тот же каталог, что и исходный файл)

Когда ранее сохраненный файл открывается для редактирования, печати или просмотра, Word создает временный файл с расширением имени файла .doc. Это расширение имени файла начинается с тильды (~), за которой следует знак доллара ($), за которым следует оставшаяся часть исходного имени файла. Этот временный файл содержит имя пользователя, открывшего файл. Этот временный файл называется «файлом владельца».

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

Этот файл уже открыт под именем пользователя. Вы хотите сделать копию этого файла для вашего использования?

Возможно, Word не сможет создать файл владельца. Например, Word не может создать файл владельца, если документ находится в общей папке, доступной только для чтения. В этом случае сообщение об ошибке изменится на следующее сообщение об ошибке:

Этот файл уже открыт другим пользователем. Хотите сделать копию этого файла для собственного использования?

Примечание. Word автоматически удаляет этот временный файл из памяти при закрытии исходного файла.

Когда вы открываете файл в общей папке UNC с помощью Word 2007, файл сначала копируется во временный каталог. Затем файл открывается из временного каталога.

Автоматическое сохранение

Папка сохранения автоматического восстановления Word

Временный файл, создаваемый при автоматическом сохранении Word, сохраняется в папке Temp, если нет действительной папки Temp. В этом случае Word сохраняет временный файл в той же папке, что и документ.

Расположение временных файлов при закрытии файла

Иногда Word может сохранять ссылку на файл после его закрытия. Это происходит, когда текст был скопирован в буфер обмена из файла. Когда вы закрываете файл, Word пытается выполнить следующие действия:

Если выделенный фрагмент, который был скопирован в буфер обмена, не содержит нескольких разделов или изображений или невелик, Word копирует часть документа в рабочий файл.

Если скопированный фрагмент содержит изображения или несколько разделов, или если файл находится на гибком диске, Word копирует весь файл во временный каталог и перемещает туда указатель.

Раздел 404 Закона Сарбейнса-Оксли (SOX) требует, чтобы все публичные компании установили внутренний контроль и процедуры.

Закон о защите конфиденциальности детей в Интернете от 1998 года (COPPA) – это федеральный закон, который налагает особые требования на операторов доменов .

План North American Electric Reliability Corporation по защите критически важной инфраструктуры (NERC CIP) представляет собой набор стандартов.

Взаимная аутентификация, также называемая двусторонней аутентификацией, представляет собой процесс или технологию, в которой оба объекта обмениваются данными .

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

Метаморфное и полиморфное вредоносное ПО – это два типа вредоносных программ (вредоносных программ), код которых может изменяться по мере их распространения.

Медицинская транскрипция (МТ) – это ручная обработка голосовых сообщений, продиктованных врачами и другими медицинскими работниками.

Электронное отделение интенсивной терапии (eICU) — это форма или модель телемедицины, в которой используются самые современные технологии.

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

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

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

Синхронная репликация — это процесс копирования данных по сети хранения, локальной или глобальной сети, поэтому .

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

Износ флэш-памяти NAND — это пробой оксидного слоя внутри транзисторов с плавающим затвором флэш-памяти NAND.

Выносливость при записи — это количество циклов программирования/стирания (P/E), которое может быть применено к блоку флэш-памяти перед сохранением .

Стек — это специальная область памяти компьютера, в которой хранятся временные переменные, созданные функцией. В стеке переменные объявляются, сохраняются и инициализируются во время выполнения.

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

В этом уроке вы узнаете,

Что такое куча?

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

Куча не управляется автоматически для вас и не так жестко управляется процессором. Это больше похоже на свободно плавающую область памяти.

КЛЮЧЕВОЕ ОТЛИЧИЕ

  • Стек – это линейная структура данных, а куча – иерархическая структура данных.
  • Память стека никогда не будет фрагментирована, в то время как память кучи может стать фрагментированной, поскольку блоки памяти сначала выделяются, а затем освобождаются.
  • Stack имеет доступ только к локальным переменным, тогда как Heap позволяет вам обращаться к переменным глобально.
  • Размер переменных стека нельзя изменить, тогда как размер переменных кучи можно изменить.
  • Память стека выделяется в непрерывном блоке, тогда как память кучи выделяется в любом случайном порядке.
  • В стеке не требуется освобождать переменные, в то время как в куче требуется освобождение памяти.
  • Выделение и освобождение стека выполняются инструкциями компилятора, тогда как выделение и освобождение кучи выполняется программистом.

Ключевые различия между стеком и кучей

< td >Распределение и освобождение td>
Параметр Стек Куча
Тип структур данных Стек — это линейная структура данных. Куча — это иерархическая структура данных.
Скорость доступа< /td> Высокоскоростной доступ Медленнее по сравнению со стеком
Управление пространством Пространство эффективно управляется ОС, поэтому память никогда не будет фрагментирована. Пространство кучи используется не так эффективно. Память может стать фрагментированной, так как блоки памяти сначала выделяются, а затем освобождаются.
Доступ Только локальные переменные Это позволяет вам глобальный доступ к переменным.
Ограничение размера пространства Ограничение размера стека в зависимости от ОС. Не имеет конкретного ограничения от размера памяти.
Изменить размер Размер переменных не может быть изменен Размер переменных может быть изменен.
Распределение памяти Память выделяется в непрерывном блоке. Память выделяется в любом случайном порядке.
Автоматически выполняется инструкциями компилятора. Это выполняется программистом вручную.
ОсвобождениеНе требует освобождения переменных. Необходимо явное освобождение.
Стоимость Меньше Больше
Реализация Стек может быть реализован тремя способами простой массив bas ed, с использованием динамической памяти и на основе связанного списка. Куча может быть реализована с использованием массива и деревьев.
Основная проблема Нехватка памяти Фрагментация памяти
Локальность ссылки Инструкции автоматического времени компиляции. Адекватный< /td>
Гибкость Фиксированный размер Возможно изменение размера
Время доступа< /td> Быстрее Медленнее

Преимущества использования стека

Вот плюсы/преимущества использования стека:

  • Помогает управлять данными методом «последним пришел – первым обслужен» (LIFO), что невозможно при использовании связанных списков и массивов.
  • При вызове функции локальные переменные сохраняются в стеке, который автоматически уничтожается после возврата.
  • Стек используется, когда переменная не используется вне этой функции.
  • Он позволяет управлять выделением и освобождением памяти.
  • Стек автоматически очищает объект.
  • Не легко повредить
  • Размер переменных нельзя изменить.

Преимущества использования кучи

  • Куча помогает найти наибольшее и минимальное число
  • Сборка мусора выполняется в памяти кучи, чтобы освободить память, используемую объектом.
  • Метод кучи также используется в приоритетной очереди.
  • Он позволяет получить глобальный доступ к переменным.
  • У кучи нет ограничений на размер памяти.

Недостатки использования стека

  • Память стека очень ограничена.
  • Создание слишком большого количества объектов в стеке может увеличить риск переполнения стека.
  • Произвольный доступ невозможен.
  • Хранилище переменных будет перезаписано, что иногда приводит к неопределенному поведению функции или программы.
  • Стек выйдет за пределы области памяти, что может привести к аварийному завершению.

Недостатки использования кучи

  • Он может предоставить максимальный объем памяти, который может предоставить ОС.
  • Для вычислений требуется больше времени.
  • Управление памятью в динамической памяти более сложно, поскольку она используется глобально.
  • Выполнение занимает слишком много времени по сравнению со стеком.

Когда использовать кучу или стек?

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

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

В общеязыковой среде выполнения (CLR) сборщик мусора (GC) служит автоматическим диспетчером памяти.Сборщик мусора управляет выделением и освобождением памяти для приложения. Для разработчиков, работающих с управляемым кодом, это означает, что вам не нужно писать код для выполнения задач управления памятью. Автоматическое управление памятью может устранить распространенные проблемы, такие как забывание освободить объект и возникновение утечки памяти или попытка доступа к памяти для уже освобожденного объекта.

В этой статье описываются основные принципы сборки мусора.

Преимущества

Сборщик мусора предоставляет следующие преимущества:

Избавляет разработчиков от необходимости вручную освобождать память.

Эффективно размещает объекты в управляемой куче.

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

Обеспечивает безопасность памяти, гарантируя, что объект не может использовать для себя память, выделенную для другого объекта.

Основы памяти

В следующем списке приведены важные концепции памяти CLR.

Каждый процесс имеет собственное отдельное виртуальное адресное пространство. Все процессы на одном компьютере совместно используют одну и ту же физическую память и файл подкачки, если он есть.

По умолчанию на 32-разрядных компьютерах каждый процесс имеет 2 ГБ виртуального адресного пространства пользовательского режима.

Как разработчик приложений, вы работаете только с виртуальным адресным пространством и никогда не управляете физической памятью напрямую. Сборщик мусора выделяет и освобождает для вас виртуальную память в управляемой куче.

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

Виртуальная память может находиться в трех состояниях:

Виртуальное адресное пространство может быть фрагментировано. Это означает, что в адресном пространстве есть свободные блоки, также известные как дыры. Когда запрашивается выделение виртуальной памяти, диспетчер виртуальной памяти должен найти один свободный блок, достаточно большой, чтобы удовлетворить этот запрос на выделение. Даже если у вас есть 2 ГБ свободного места, выделение, требующее 2 ГБ, будет неудачным, если только все это свободное пространство не находится в одном адресном блоке.

У вас может закончиться память, если недостаточно виртуального адресного пространства для резервирования или физического пространства для фиксации.

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

Распределение памяти

При инициализации нового процесса среда выполнения резервирует для процесса непрерывную область адресного пространства. Это зарезервированное адресное пространство называется управляемой кучей. Управляемая куча поддерживает указатель на адрес, по которому будет размещен следующий объект в куче. Первоначально этот указатель установлен на базовый адрес управляемой кучи. Все ссылочные типы размещаются в управляемой куче. Когда приложение создает первый ссылочный тип, для него выделяется память по базовому адресу управляемой кучи. Когда приложение создает следующий объект, сборщик мусора выделяет для него память в адресном пространстве сразу после первого объекта. Пока доступно адресное пространство, сборщик мусора продолжает таким же образом выделять место для новых объектов.

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

Освобождение памяти

Оптимизирующий механизм сборщика мусора определяет наилучшее время для выполнения сборки на основе произведенных выделений памяти. Когда сборщик мусора выполняет сборку, он освобождает память для объектов, которые больше не используются приложением. Он определяет, какие объекты больше не используются, изучая корни приложения. Корни приложения включают статические поля, локальные переменные в стеке потока, регистры ЦП, дескрипторы сборщика мусора и очередь финализации. Каждый корень либо ссылается на объект в управляемой куче, либо имеет значение null. Сборщик мусора может запросить у остальной части среды выполнения эти корни. Используя этот список, сборщик мусора создает граф, содержащий все объекты, доступные из корней.

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

Память сжимается, только если коллекция обнаруживает значительное количество недоступных объектов. Если все объекты в управляемой куче выдерживают сборку, сжатие памяти не требуется.

Для повышения производительности среда выполнения выделяет память для больших объектов в отдельной куче. Сборщик мусора автоматически освобождает память для больших объектов. Однако, чтобы избежать перемещения больших объектов в памяти, эта память обычно не уплотняется.

Условия для сборки мусора

Сборка мусора происходит, когда выполняется одно из следующих условий:

В системе недостаточно физической памяти. Это определяется либо уведомлением о нехватке памяти от ОС, либо нехваткой памяти, указанной хостом.

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

Вызывается метод GC.Collect. Почти во всех случаях вам не нужно вызывать этот метод, потому что сборщик мусора работает непрерывно. Этот метод в основном используется для уникальных ситуаций и тестирования.

Управляемая куча

После того как CLR инициализирует сборщик мусора, он выделяет сегмент памяти для хранения объектов и управления ими. Эта память называется управляемой кучей, в отличие от собственной кучи в операционной системе.

Для каждого управляемого процесса существует управляемая куча. Все потоки процесса выделяют память для объектов в одной куче.

Для резервирования памяти сборщик мусора вызывает функцию Windows VirtualAlloc и резервирует по одному сегменту памяти для управляемых приложений. Сборщик мусора также резервирует сегменты по мере необходимости и возвращает сегменты операционной системе (после очистки их от любых объектов), вызывая функцию Windows VirtualFree.

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

Чем меньше объектов размещено в куче, тем меньше работы должен выполнить сборщик мусора. Когда вы выделяете объекты, не используйте округленные значения, которые превышают ваши потребности, например, выделяйте массив из 32 байтов, когда вам нужно всего 15 байтов.

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

Навязчивость (частота и продолжительность) сборок мусора является результатом объема выделений и объема оставшейся памяти в управляемой куче.

Куча может рассматриваться как совокупность двух куч: кучи больших объектов и кучи маленьких объектов. Куча больших объектов содержит объекты размером 85 000 байт и больше, которые обычно представляют собой массивы. Объект экземпляра редко бывает очень большим.

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

Поколения

Алгоритм GC основан на нескольких соображениях:

  • Быстрее сжимать память для части управляемой кучи, чем для всей управляемой кучи.
  • У новых объектов меньше срок службы, а у старых — больше.
  • Новые объекты, как правило, связаны друг с другом и доступны для приложения примерно в одно и то же время.

Сборка мусора в основном происходит при утилизации недолговечных объектов. Для оптимизации производительности сборщика мусора управляемая куча делится на три поколения: 0, 1 и 2, поэтому она может обрабатывать долгоживущие и короткоживущие объекты отдельно. Сборщик мусора сохраняет новые объекты в поколении 0. Объекты, созданные в начале жизненного цикла приложения, которые сохранились после сборок, перемещаются и сохраняются в поколениях 1 и 2.Поскольку сжимать часть управляемой кучи быстрее, чем всю кучу, эта схема позволяет сборщику мусора освобождать память в определенном поколении, а не освобождать память для всей управляемой кучи каждый раз, когда он выполняет сборку.

Поколение 0. Это самое молодое поколение, содержащее недолговечные объекты. Примером недолговечного объекта является временная переменная. Сборка мусора чаще всего происходит в этом поколении.

Вновь выделенные объекты образуют новое поколение объектов и неявно являются коллекциями поколения 0. Однако если это большие объекты, они помещаются в кучу больших объектов (LOH), которую иногда называют поколение 3. Поколение 3 — это физическое поколение, которое логически собрано как часть поколения 2.

Большинство объектов утилизируются для сборки мусора в поколении 0 и не сохраняются в следующем поколении.

Если приложение пытается создать новый объект, когда поколение 0 заполнено, сборщик мусора выполняет сборку, пытаясь освободить адресное пространство для объекта. Сборщик мусора начинает с проверки объектов в поколении 0, а не всех объектов в управляемой куче. Одна лишь коллекция поколения 0 часто требует памяти, достаточной для того, чтобы приложение могло продолжать создавать новые объекты.

Поколение 1. Это поколение содержит недолговечные объекты и служит буфером между короткоживущими и долгоживущими объектами.

После того, как сборщик мусора выполнит сборку поколения 0, он уплотнит память для доступных объектов и повысит их уровень до поколения 1. Поскольку объекты, пережившие сборку, как правило, имеют более длительное время жизни, имеет смысл повысить их уровень до более высокого поколения. . Сборщику мусора не нужно повторно проверять объекты поколений 1 и 2 каждый раз, когда он выполняет сборку поколения 0.

Если коллекция поколения 0 не освобождает достаточно памяти для приложения, чтобы создать новый объект, сборщик мусора может выполнить сборку поколения 1, а затем поколения 2. Объекты поколения 1, сохранившиеся после коллекций, переводятся в поколение 2. .

Поколение 2. Это поколение содержит долгоживущие объекты. Примером долгоживущего объекта является объект в серверном приложении, содержащий статические данные, действующие в течение всего процесса.

Объекты поколения 2, сохранившиеся в коллекции, остаются в поколении 2 до тех пор, пока не будет определено, что они недоступны в будущей коллекции.

Объекты в куче больших объектов (которую иногда называют поколение 3) также собираются в поколении 2.

Сборка мусора происходит в определенных поколениях в зависимости от условий. Сбор поколения означает сбор объектов в этом поколении и во всех его младших поколениях. Сборка мусора поколения 2 также называется полной сборкой мусора, поскольку она утилизирует объекты всех поколений (то есть все объекты в управляемой куче).

Выживание и продвижение

Объекты, которые не были утилизированы при сборке мусора, называются уцелевшими и переходят в следующее поколение:

  • Объекты, пережившие сборку мусора поколения 0, переходят в поколение 1.
  • Объекты, пережившие сборку мусора первого поколения, переносятся на второе поколение.
  • Объекты, пережившие сборку мусора поколения 2, остаются в поколении 2.

Когда сборщик мусора обнаруживает, что вероятность выживания в поколении высока, он увеличивает порог выделения для этого поколения. Следующая коллекция получает значительный объем восстановленной памяти. CLR постоянно уравновешивает два приоритета: не допускать слишком большого рабочего набора приложения из-за задержки сборки мусора и не допускать слишком частого запуска сборки мусора.

Эфемерные поколения и сегменты

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

Эфемерные поколения размещаются в сегменте памяти, известном как эфемерный сегмент. Каждый новый сегмент, полученный сборщиком мусора, становится новым эфемерным сегментом и содержит объекты, пережившие сборку мусора поколения 0. Старый эфемерный сегмент становится сегментом нового поколения 2.

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

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

Объем памяти, освобождаемой при сборке эфемерного мусора, ограничен размером эфемерного сегмента. Объем освобождаемой памяти пропорционален пространству, занятому мертвыми объектами.

Что происходит во время сборки мусора

Сборка мусора состоит из следующих этапов:

Этап маркировки, который находит и создает список всех живых объектов.

Этап перемещения, который обновляет ссылки на объекты, которые будут сжаты.

Фаза уплотнения, которая восстанавливает пространство, занимаемое мертвыми объектами, и уплотняет уцелевшие объекты. Фаза сжатия перемещает объекты, пережившие сборку мусора, к более старому концу сегмента.

Поскольку коллекции поколения 2 могут занимать несколько сегментов, объекты, переведенные в поколение 2, могут быть перемещены в более старый сегмент. Оставшиеся в живых как 1-го, так и 2-го поколения можно переместить в другой сегмент, потому что они переведены во 2-е поколение.

  • Ограничение памяти в контейнере.
  • Параметры конфигурации времени выполнения GCHeapHardLimit или GCHeapHardLimitPercent.

Сборщик мусора использует следующую информацию, чтобы определить, являются ли объекты живыми:

Корни стека. Переменные стека, предоставляемые JIT-компилятором и обходчиком стека. JIT-оптимизация может удлинять или сокращать участки кода, в которых переменные стека передаются сборщику мусора.

Дескрипторы сборки мусора. Обрабатывает, которые указывают на управляемые объекты и могут быть выделены пользовательским кодом или общеязыковой средой выполнения.

Статические данные. Статические объекты в доменах приложений, которые могут ссылаться на другие объекты. Каждый домен приложения отслеживает свои статические объекты.

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

На следующем рисунке показан поток, который запускает сборку мусора и приводит к приостановке других потоков.

Неуправляемые ресурсы

Для большинства объектов, создаваемых вашим приложением, вы можете полагаться на сборку мусора для автоматического выполнения необходимых задач управления памятью. Однако неуправляемые ресурсы требуют явной очистки. Наиболее распространенный тип неуправляемого ресурса — это объект, который является оболочкой ресурса операционной системы, например дескриптор файла, дескриптор окна или сетевое соединение. Хотя сборщик мусора может отслеживать время жизни управляемого объекта, который инкапсулирует неуправляемый ресурс, он не имеет специальных знаний о том, как очистить ресурс.

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

Вы также должны предоставить способ освобождения неуправляемых ресурсов на случай, если потребитель вашего типа забудет вызвать Dispose . Вы можете либо использовать безопасный дескриптор для переноса неуправляемого ресурса, либо переопределить метод Object.Finalize().

Дополнительную информацию об очистке неуправляемых ресурсов см. в разделе Очистка неуправляемых ресурсов.

Как объект попадает в LOH

Если размер объекта больше или равен 85 000 байт, он считается большим объектом. Это число было определено путем настройки производительности. Когда запрос на выделение объекта составляет 85 000 или более байт, среда выполнения выделяет его в куче больших объектов.

Чтобы понять, что это значит, полезно изучить некоторые основы сборщика мусора.

Сборщик мусора — это сборщик поколений. У него три поколения: поколение 0, поколение 1 и поколение 2. Причина существования трех поколений заключается в том, что в хорошо настроенном приложении большинство объектов умирает в поколении 0. Например, в серверном приложении выделения, связанные с каждым запросом, должны умирать после завершения запроса.Запросы на распределение во время полета попадут в gen1 и умрут там. По сути, gen1 действует как буфер между областями молодых объектов и областями долгоживущих объектов.

Вновь выделенные объекты образуют новое поколение объектов и неявно являются коллекциями поколения 0. Однако, если это большие объекты, они помещаются в кучу больших объектов (LOH), которую иногда называют поколением 3. Поколение 3 — это физическое поколение, которое логически собирается как часть поколения 2.

Большие объекты относятся к поколению 2, поскольку они собираются только во время сбора поколению 2. Когда собирается поколение, все его более молодые поколения также собираются. Например, когда происходит сборка мусора поколения 1, собираются как поколение 1, так и поколение 0. И когда происходит GC поколения 2, вся куча собирается. По этой причине сборщик мусора поколения 2 также называется полным сборщиком мусора. В этой статье речь идет о сборщике мусора поколения 2, а не о полном сборщике мусора, но эти термины взаимозаменяемы.

Поколения обеспечивают логическое представление кучи GC. Физически объекты находятся в управляемых сегментах кучи. сегмент управляемой кучи – это фрагмент памяти, который сборщик мусора резервирует у ОС, вызывая функцию VirtualAlloc от имени управляемого кода. При загрузке среды CLR GC выделяет два начальных сегмента кучи: один для небольших объектов (куча малых объектов, или SOH), а другой — для больших объектов (куча больших объектов).

Запросы на выделение затем удовлетворяются путем помещения управляемых объектов в эти сегменты управляемой кучи. Если размер объекта меньше 85 000 байт, он помещается в сегмент для SOH; в противном случае он помещается в сегмент LOH. Сегменты фиксируются (меньшими порциями) по мере того, как на них выделяется все больше и больше объектов. Для SOH объекты, пережившие сборку мусора, переходят в следующее поколение. Объекты, пережившие коллекцию поколения 0, теперь считаются объектами поколения 1 и так далее. Однако объекты, пережившие самое старое поколение, по-прежнему считаются относящимися к самому старому поколению. Другими словами, выжившие из поколения 2 являются объектами поколения 2; а оставшиеся в живых из LOH являются объектами LOH (которые собираются с помощью gen2).

Код пользователя может размещаться только в поколении 0 (маленькие объекты) или LOH (крупные объекты). Только GC может «распределять» объекты в поколении 1 (путем повышения выживших из поколения 0) и поколения 2 (путем повышения выживших из поколения 1).

При запуске сборки мусора сборщик мусора прослеживает живые объекты и сжимает их. Но поскольку уплотнение обходится дорого, GC заметает LOH; он создает список свободных объектов из мертвых объектов, которые можно повторно использовать позже для удовлетворения запросов на выделение больших объектов. Соседние мертвые объекты объединяются в один свободный объект.

На рисунке 1 показан сценарий, в котором GC формирует поколение 1 после первого GC поколения 0, где Obj1 и Obj3 мертвы, и формирует поколение 2 после первого GC поколения 1, где Obj2 и Obj5 мертвы. Обратите внимание, что этот и следующие рисунки приведены только для иллюстрации; они содержат очень мало объектов, чтобы лучше показать, что происходит в куче. На самом деле в сборщик мусора обычно вовлечено гораздо больше объектов.


Рисунок 1. Сборщик мусора поколения 0 и поколения 1.

На рис. 2 показано, что после сборки мусора 2-го поколения, которая обнаружила, что Obj1 и Obj2 мертвы, сборщик мусора формирует непрерывное свободное пространство из памяти, которая раньше была занята Obj1 и Obj2 , которая затем использовалась для удовлетворения запроса на выделение для Объект4. Пространство после последнего объекта Obj3 до конца сегмента также можно использовать для удовлетворения запросов на выделение.


Рисунок 2. После сборки мусора второго поколения

Если свободного места недостаточно для размещения запросов на выделение больших объектов, GC сначала пытается получить дополнительные сегменты от ОС. Если это не удается, он запускает сборщик мусора 2-го поколения в надежде освободить место.

Во время сборки мусора поколения 1 или поколения 2 сборщик мусора освобождает сегменты, на которых нет живых объектов, обратно в ОС, вызывая функцию VirtualFree. Пространство после последнего живого объекта до конца сегмента освобождается (за исключением эфемерного сегмента, где живут gen0/gen1, где сборщик мусора сохраняет некоторые зафиксированные объекты, потому что ваше приложение будет выделять их сразу). А свободные места остаются занятыми, даже если они сбрасываются, а это означает, что ОС не нужно записывать данные в них обратно на диск.

Поскольку LOH собирается только во время GC поколения 2, сегмент LOH может быть освобожден только во время такого GC.На рис. 3 показан сценарий, в котором сборщик мусора освобождает один сегмент (сегмент 2) обратно в ОС и освобождает больше места в оставшихся сегментах. Если ему нужно использовать освобожденное пространство в конце сегмента для удовлетворения запросов на выделение больших объектов, он снова выделяет память. (Объяснение фиксации/отмены см. в документации по VirtualAlloc.


Рисунок 3: LOH после сборки мусора 2-го поколения

Когда собирается крупный объект?

Как правило, GC происходит при одном из следующих трех условий:

Распределение превышает пороговое значение поколения 0 или большого объекта.

Порог является свойством поколения. Порог для поколения устанавливается, когда сборщик мусора выделяет в него объекты. Когда порог превышен, сборщик мусора запускается в этом поколении. Когда вы выделяете маленькие или большие объекты, вы используете пороги поколения 0 и LOH соответственно. Когда сборщик мусора выделяет память для поколений 1 и 2, он потребляет их пороговые значения. Эти пороги динамически настраиваются во время работы программы.

Это типичный случай; большинство сборщиков мусора происходит из-за выделения памяти в управляемой куче.

Вызывается метод GC.Collect.

Если вызывается метод GC.Collect() без параметров или передается другая перегрузка GC.MaxGeneration в качестве аргумента, LOH собирается вместе с остальной частью управляемой кучи.

В системе недостаточно памяти.

Это происходит, когда сборщик мусора получает от ОС уведомление о нехватке памяти. Если сборщик мусора считает, что сборщик мусора поколения 2 будет продуктивным, он запускает его.

Влияние на производительность LOH

Выделения в куче больших объектов влияют на производительность следующим образом.

Среда CLR гарантирует, что память для каждого выдаваемого ею нового объекта будет очищена. Это означает, что в стоимости выделения большого объекта преобладает очистка памяти (если только она не запускает сборщик мусора). Если для очистки одного байта требуется два цикла, то для очистки самого маленького большого объекта требуется 170 000 циклов. Очистка памяти объекта размером 16 МБ на компьютере с частотой 2 ГГц занимает примерно 16 мс. Это довольно большие затраты.

Поскольку LOH и поколение 2 собираются вместе, при превышении порога любого из них запускается сбор поколения 2. Если коллекция поколения 2 запускается из-за LOH, поколение 2 не обязательно будет намного меньше после GC. Если данных о поколении 2 не так много, это оказывает минимальное влияние. Но если поколение 2 большое, это может вызвать проблемы с производительностью, если запущено много сборщиков мусора поколения 2. Если много больших объектов выделено на временной основе, а у вас большой SOH, возможно, вы тратите слишком много времени на сборщик мусора. Кроме того, затраты на размещение могут значительно увеличиться, если вы продолжите выделять и освобождать действительно большие объекты.

Элементы массива со ссылочными типами.

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

Если num_nodes велико, сборщику мусора необходимо просмотреть не менее двух ссылок на элемент. Альтернативный подход — хранить индекс правого и левого узлов:

Вместо того, чтобы ссылаться на данные левого узла как left.d , вы ссылаетесь на них как на binary_tr[left_index].d . И сборщику мусора не нужно просматривать какие-либо ссылки на левый и правый узлы.

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

Сбор данных о производительности для LOH

Прежде чем собирать данные об эффективности для определенной области, вы уже должны были сделать следующее:

Найдены доказательства того, что вам следует обратить внимание на эту область.

Исчерпал другие известные вам области, но не нашел ничего, что могло бы объяснить обнаруженную вами проблему с производительностью.

Дополнительную информацию об основах памяти и ЦП см. в блоге Разберитесь в проблеме, прежде чем пытаться найти решение.

Вы можете использовать следующие инструменты для сбора данных об эффективности LOH:

Коллекции второго поколения

Отображает количество общих сборок поколения 2 с момента запуска процесса.Счетчик увеличивается в конце сборки поколения 2 (также называемой полной сборкой мусора). Этот счетчик отображает последнее наблюдаемое значение.

Большой размер кучи объектов

Отображает текущий размер LOH в байтах, включая свободное пространство. Этот счетчик обновляется в конце сборки мусора, а не при каждом выделении памяти.

Распространенный способ просмотра счетчиков производительности — с помощью системного монитора (perfmon.exe). Используйте «Добавить счетчики», чтобы добавить интересный счетчик для процессов, которые вам интересны. Вы можете сохранить данные счетчика производительности в файл журнала, как показано на экране 4:

Рисунок 4: LOH после сборки мусора 2-го поколения

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

Мы рекомендуем использовать события ETW вместо счетчиков производительности, поскольку ETW предоставляет гораздо больше информации.

События ETW

Сборщик мусора предоставляет широкий набор событий ETW, которые помогут вам понять, что делает куча и почему. В следующих сообщениях блога показано, как собирать и анализировать события GC с помощью ETW:

Чтобы выявить чрезмерное количество общих сборок поколения 2, вызванное временными выделениями LOH, просмотрите столбец «Причина срабатывания» для общих сборок. Для простого теста, который выделяет только временные большие объекты, вы можете собрать информацию о событиях ETW с помощью следующей командной строки PerfView:

Результат примерно такой:

Рис. 5. События ETW, показанные с помощью PerfView

Как видите, все сборщики мусора относятся к сборщикам мусора 2-го поколения, и все они запускаются AllocLarge, что означает, что этот сборщик мусора срабатывает при выделении большого объекта. Мы знаем, что эти распределения являются временными, поскольку в столбце LOH Survival Rate % указано 1%.

Вы можете собирать дополнительные события ETW, чтобы узнать, кто выделил эти большие объекты. Следующая командная строка:

собирает событие AllocationTick, которое запускается примерно каждые 100 000 выделений. Другими словами, событие запускается каждый раз, когда выделяется большой объект. Затем вы можете просмотреть одно из представлений GC Heap Alloc, в котором показаны стеки вызовов, выделяющие большие объекты:

Рисунок 6. Представление GC Heap Alloc

Как видите, это очень простой тест, который просто выделяет большие объекты из своего метода Main.

Отладчик

Команды отладки, упомянутые в этом разделе, применимы к отладчикам Windows.

Ниже показан пример результатов анализа LOH:

Размер кучи LOH составляет (16 754 224 + 16 699 288 + 16 284 504) = 49 738 016 байт. Между адресами 023e1000 и 033db630 8 008 736 байт занято массивом объектов System.Object, 6 663 696 байт занято массивом объектов System.Byte и 2 081 792 байта занято свободным пространством.

Иногда отладчик показывает, что общий размер LOH меньше 85 000 байт. Это происходит потому, что сама среда выполнения использует LOH для выделения некоторых объектов, которые меньше, чем большой объект.

Поскольку LOH не сжат, иногда считается, что LOH является источником фрагментации. Фрагментация означает:

Фрагментация управляемой кучи, на которую указывает количество свободного места между управляемыми объектами. В SoS команда !dumpheap –type Free отображает количество свободного места между управляемыми объектами.

Фрагментация адресного пространства виртуальной памяти (ВМ), то есть памяти, помеченной как MEM_FREE . Вы можете получить его с помощью различных команд отладчика в Windbg.

В следующем примере показана фрагментация пространства виртуальных машин:

Часто можно увидеть фрагментацию ВМ, вызванную временными большими объектами, которые требуют, чтобы сборщик мусора часто получал новые сегменты управляемой кучи из ОС и освобождал пустые обратно в ОС.

Чтобы проверить, не вызывает ли LOH фрагментацию ВМ, можно установить точку останова на VirtualAlloc и VirtualFree, чтобы увидеть, кто их вызывал. Например, чтобы узнать, кто пытался выделить из ОС фрагменты виртуальной памяти размером более 8 МБ, можно установить такую ​​точку останова:

Эта команда переходит в отладчик и показывает стек вызовов, только если VirtualAlloc вызывается с размером выделения более 8 МБ (0x800000).

В CLR 2.0 добавлена ​​функция VM Hoarding, которая может быть полезна в сценариях, в которых сегменты (в том числе в кучах больших и малых объектов) часто собираются и освобождаются. Чтобы указать VM Hoarding, вы указываете флаг запуска с именем STARTUP_HOARD_GC_VM через API хостинга. Вместо того, чтобы возвращать ОС пустые сегменты, CLR освобождает память для этих сегментов и помещает их в резервный список. (Обратите внимание, что CLR не делает этого для слишком больших сегментов.) Позже CLR использует эти сегменты для удовлетворения запросов на новые сегменты. В следующий раз, когда вашему приложению понадобится новый сегмент, CLR использует его из этого резервного списка, если сможет найти достаточно большой сегмент.

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

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

Читайте также:

Коллектор рабочей станции/сервера 32-разрядный 64-разрядный
ГХ рабочей станции 16 МБ 256 МБ
ГХ сервера 64 МБ 4 ГБ
Серверный GC с > 4 логическими процессорами 32 МБ 2 ГБ
Серверный GC с > 8 логическими процессорами 16 МБ 1 ГБ