Статьи

Утилиты MMTk

Диаграмма классов счетчиков
Языковые виртуальные машины высокого уровня — это ключевая тема, интересующая исследователей, занимающихся виртуальными средами исполнения. В качестве виртуальной машины с открытым исходным кодом, выпущенной в 16 университетах, уже в 2001 году Jikes RVM стал основным стимулом для многих исследований. Сборщики мусора для Jikes RVM построены на платформе, известной как инструментарий управления памятью (MMTk). Ключевые композиционные элементы в MMTk — это утилиты, политики и планы. Помимо этого, пакет org.mmtk.harness содержит тестовые наборы для проводки MMTk. Проверка работоспособности включена в пакет org.mmtk.harness.sanity. GcSanity — это средство проверки работоспособности коллекции, которое делает снимки до и после коллекции, чтобы убедиться, что живые объекты после коллекции совпадают с существующими до коллекции. Дальнейшие опции реализованы в классах org.mmtk.harness.опции. Мы смотрели наполитики и планы . В этом посте мы рассмотрим пакет утилит MMTk, который реализует механизмы MMTk.

MMTk поставляется с классами утилит, которые обеспечивают механизм для управления памятью, для нескольких политик и планов, которые используют эти политики. Идеальный пример, показывающий использование пакета утилит, — это
константы интерфейса . Все классы либо реализуют интерфейс Constants, либо являются подклассами классов, которые реализуют интерфейс.

1. Распределение
Пакет org.mmtk.utility.alloc обрабатывает выделение. Allocator — это базовый класс, обеспечивающий основу для локального распределения процессора. Это обеспечивает механизм повторных попыток, чтобы предотвратить медленное выделение пути, вызывающее сборку мусора, нарушая предположение о непрерывности. Распределитель также обеспечивает выравнивание запросов в соответствии с запросами. Этот класс очень важен в сборке мусора как базовый класс для всех алгоритмов распределителя. Неправильная обработка этого затруднит отслеживание ошибок, когда выделения могут вызвать сборку мусора, или сборка мусора может сразу следовать за распределением.

Метод alignAllocation () принимает область для выравнивания и выравнивает запрос в соответствии с запрошенным выравниванием и смещением, оптимизируя с известным выравниванием для алгоритмов распределителя. Этот метод возвращает выровненный адрес.

Ошибка последовательного выделения потоков подсчитывается методом defineCollectionAttempts (). fillAlignmentGap () получает начальный и конечный адреса и заполняет регион значением выравнивания. Минимальный размер, гарантирующий выделение заданного количества байтов при указанном выравнивании, вычисляется методом getMaximumAlignedSize ().

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

2. Распределение указателя удара
Это реализуется классом BumpPointer , который расширяет абстрактный класс Allocator. B UMP Указатель просматривает выделенные объекты по линейному закону. Для достижения параллелизма этот класс поддерживает заголовок в области зернистости 1 или более блоков. Минимальный размер области составляет 32678 байт. Следовательно, издержки на 3 или 4 слова составляют менее 0,05% от всего пробела. BumpPointer инициализируется предоставлением пространства для точки столкновения, указывающей, разрешено ли линейное сканирование в регионе. Метод linearScan () выполняет линейное сканирование объектов, выделенных указателем «bump», а scanRegion () сканирует одну непрерывную область.

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

Место выделяется для нового объекта, вызывая alloc (). Этот метод часто выполняется и чувствителен к оптимизирующему компилятору. Когда указатель удара достигает внутреннего предела, вызывается allocSlow () . Этот метод никогда не должен быть встроен оптимизирующим компилятором и, следовательно, аннотирован @NoInline для принудительного вывода из строки.

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

Address
является реализацией заглушки типа Address, используемой системой времени выполнения и сборщиком для обозначения машинных адресов. Единица распределения обозначается как карта, которая помечена адресом, который находится внутри карты. Предоставляя адрес объекта, создающего новую карту, адрес, который находится внутри карты, и размер ожидающего выделения в байтах, createCardAnchor () создает запись, где начало карты относительно начала объекта , Начало карты, соответствующей данному адресу, можно получить, вызвав getCard () . Аналогично, адрес метаданных карты можно получить, указав адрес карты, вызвав getCardMetaData () .

Следующий регион из связанного списка регионов можно получить с помощью
getNextRegion (). Аналогично, setNextRegion () используется для установки следующего региона в связанном списке. clearNextRegion () очищает следующий указатель региона в связанном списке.

Адрес DATA_END из заголовка региона может быть
получен с помощью getDataEnd (), предоставив адрес области указателя удара. setDataEnd () используется для установки нового адреса DATA_END из заголовка. Аналогично, getRegionLimit () и setRegionLimit () возвращают или сохраняют конечный адрес данного региона соответственно. Самый низкий адрес, где могут храниться данные, может быть получен методом getDataStart () для данного региона. updateMetaData () используется для обновления метаданных, отражающих добавление нового региона. Если область указателя неровностей была использована, но при этом доступна смежная область, потреблениеNextRegion ()потребляет его и возвращает начало региона, удовлетворяющего невыполненному запросу выделения.

3. Распределение блоков
Блоки — это единица хранения в 2 ^ n байтов, которые не являются общими (для локальных потоков) и крупнозернистыми. Ресурс виртуальной памяти обеспечивает пространство виртуальной памяти. Здесь страницы, используемые блоками, отвечают за ресурс памяти. BlockAllocator реализует различные размеры структуры данных блока. alloc () выделяет блок и возвращает первые используемые байты блока. Блок освобождается вызовом free (). Если блок полностью свободен, блок возвращается в ресурс виртуальной памяти. В противном случае, если блок является просто блоком подстраницы, блок добавляется в свободный список.

4. GCspy Integration
GCspy 2.0 — это инструмент, который помогает анализировать кучу, который часто используется для понимания использования памяти и эффективности сборщиков мусора в нашем проекте. Однако разработка GCspy отстает от разработки ядра Jikes RVM [10]. Данные для GCspy собираются с использованием gcspyGatherData () в классах . Пакет org.mmtk.utility.gcspy содержит классы для интеграции GCspy, а org.mmtk.utility.gcspy.drivers содержит драйверы GCspy для сборщиков MMTk.

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

 [Forward Link | Backward Link | Treadmill | Payload ----->]

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

 
Это предполагает, что язык реализации и язык реализации одинаковы. Это хорошо работает с Jikes RVM, так как это Java. Однако для использования с другими реализациями VM на других языках класс двусвязных списков, от которого зависит Treadmill, должен быть переписан.
 
Если созданный экземпляр должен быть разделен между потоками, что определяется логическим параметром « shared», предоставленным в качестве параметра в конструкторе, доступ будет синхронизирован с блокировками. Узел добавляется к беговой дорожке во время выделения, используя addToTreadmill () .

6. Распределение больших объектов
Это реализовано в LargeObjectLocal, который расширяет абстрактный класс LargeObjectAllocator. Каждый экземпляр обеспечивает быстрый несинхронизированный доступ к беговой дорожке и привязан к одному ЦП. Следовательно, это не должно быть общим для разных процессоров, поскольку они обеспечивают действительно параллельные потоки.
Учитывая c процессоров и t пространств беговой дорожки, для каждой пары {CPU, Treadmill} будет не более * экземпляров этого класса.

7. Ресурс страницы
Выделение страниц для пространства управляется абстрактным классом PageResource . При запросе пространства проверяются страница, бюджет страницы и использование виртуального адресного пространства. Если запрос не может быть выполнен, запускается сборка мусора. MonotonePageResource , который является подклассом этого класса, обрабатывает монотонное использование пространства. Точно так же другой подкласс, FreeListPageResource, обрабатывает специальное использование. Копирующие коллекторы монотонно распределяют пространство перед тем, как освободить все пространство. Следовательно, MonotonePageResource полезен для них. Хотя MonotonePageResource более ограничен, им легче управлять.

8. Управление ростом кучи
HeapGrowthManager наблюдает за использованием кучи и загрузкой GC, и соответственно увеличивает и уменьшает размер кучи. T его класс, а все остальные классы в пакете org.mmtk.utility.heap содержит механизмы , связанные с кучей.

9. Sanity Checker
Проверки работоспособности для простых сборщиков обрабатываются классами в пакете org.mmtk.utility.sanitychecker . SanityChecker — основной класс, обрабатывающий проверку работоспособности . SanityDataTable реализует простую хеш- таблицу для хранения и извлечения для каждого объекта информации о проверках работоспособности .

10. Статистика
Пакет org.mmtk.utility.statisticsсодержит несколько счетчиков, реализующих абстрактный класс Counter для нескольких целей подсчета. SizeCounter, объединяющие два EventCounter объектов , подсчитывать количество событий и объем. Класс Xml записывает вывод в формате XML.

11. Deque
Классы расширяющие Deque
Пакет org.mmtk.utility.deque определяет двусвязную двустороннюю очередь (deque). Хотя двойное связывание немного увеличивает потребность в пространстве, это стоит компромисса, поскольку это обеспечивает эффективный буфер и такие операции, как сортировка.
 
LocalSSB реализует локальный несинхронизированный буфер последовательного хранилища. Это используется в критическом коде, таком как рабочая очередь сбора мусора и буфер записи, используемый многими сборщиками. Следовательно, это реализовано максимально эффективно в пространстве и времени. Каждый экземпляр имеет указатель удара и указатель на sharedDeque. Этот класс следует за FIFO, хотя он не реализует распаковку. TraceBuffer поддерживает постановку в очередь и снятие с очереди данных трассировки и массовую обработку буфера.
12. Журнал
Класс журнала используется для регистрации трассировки и ошибок. M размер essage буфера намеренно держал большой (3000 символов), так как замок класс Jikes РВМ регистрирует значительное количество информации во время потенциального GC тупика.