«Если рабочий хочет хорошо выполнять свою работу, он должен сначала заточить свои инструменты» — Конфуций, «Аналитики Конфуция. Лу Лингун»
титульная страница > программирование > Управление памятью в собственном образе GraalVM

Управление памятью в собственном образе GraalVM

Опубликовано 7 ноября 2024 г.
Просматривать:310

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

Сбор мусора

Сборка мусора (GC) играет ключевую роль в современных языках программирования, таких как Java и Go. Он автономно обнаруживает и перерабатывает неиспользуемую память, тем самым избавляя разработчиков от необходимости вручную управлять памятью. Концепция GC первоначально появилась в языке программирования LISP в конце 1950-х годов, ознаменовав введение автоматизированного управления памятью.

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

  • Предотвращение утечек памяти и эффективное использование памяти.
  • Упрощены процессы разработки и повышена стабильность программы.

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

Алгоритм подсчета ссылок [Джордж Э. Коллинз, 1966]

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

Рассмотрим следующий код:

Сначала создайте демонстрационную строку со значением, на которую ссылается d (Рис. 1).

String d = new String("demo");

Memory Management in GraalVM Native Image

Рис. 1. После создания строки

Затем установите d в ноль. Счетчик ссылок демо-версии равен нулю. В алгоритме подсчета ссылок память для демонстрации должна быть освобождена (Рисунок 2).

d =null; // Reference count of 'demo' becomes zero, prompting garbage collection.

Memory Management in GraalVM Native Image

Рис. 2. Когда ссылка обнуляется

Алгоритм подсчета ссылок работает во время выполнения программы, избегая событий Stop-The-World, которые временно останавливают программу для сбора мусора. Однако его основным недостатком является неспособность обрабатывать циклические ссылки (Рисунок 3).

Например:

public class CircularReferenceDemo {

  public CircularReferenceDemo reference;
  private String name;

  public CircularReferenceDemo(String name) {
    this.name = name;
  }

  public void setReference(CircularReferenceDemo ref) {
    this.reference = ref;
  }

  public static void main(String[] args) {
    CircularReferenceDemo objA = new CircularReferenceDemo("Ref_A");
    CircularReferenceDemo objB = new CircularReferenceDemo("Ref_B");

    objA.setReference(objB);
    objB.setReference(objA);

    objA = null;
    objB = null;
  }
}

Здесь, несмотря на обнуление внешних ссылок, взаимные ссылки между objA и objB предотвращают сборку мусора.

Memory Management in GraalVM Native Image

Рис. 3. Циклические ссылки

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

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

Алгоритм анализа достижимости [1978]

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

Как показано на изображении ниже, объекты в синем кружке следует сохранить, а объекты в сером кружке можно сдать на переработку (Рис. 4).

Memory Management in GraalVM Native Image

Рис. 4. Утечка памяти

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

Обычно объекты Java, рассматриваемые как корни GC, включают:

  • Локальные переменные в области текущей области метода.
  • Активные потоки Java.
  • Статические поля из классов.
  • Ссылки JNI из машинного кода.

Обзор собственного образа GraalVM

GraalVM предлагает опережающий (AOT) компилятор, который преобразует приложения Java в автономные исполняемые двоичные файлы, известные как собственные образы GraalVM. Эти двоичные файлы, разработанные Oracle Labs
инкапсулировать классы приложений и библиотек, а также компоненты среды выполнения, такие как GC, что позволяет выполнять операции без среды выполнения Java (JRE).

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

Основы Substrate VM

Виртуальная машина Substrate является неотъемлемой частью пакета GraalVM, управляемого Oracle Labs. Это улучшенная JVM, которая не только поддерживает упреждающую компиляцию (AOT), но также облегчает выполнение языков, помимо Java, таких как JavaScript, Python, Ruby и даже родных языков, таких как C и C. По своей сути Substrate VM представляет собой сложную платформу, которая позволяет GraalVM компилировать приложения Java в автономные двоичные файлы. Выполнение этих двоичных файлов не требует использования обычной виртуальной машины Java (JVM), что упрощает развертывание и
операционные процессы.

Одной из важнейших особенностей Substrate VM является специализированный сборщик мусора, который идеально настроен для приложений, которым требуется низкая задержка и минимальное потребление памяти. Этот сборщик мусора умеет обрабатывать уникальную структуру памяти и операционную модель, отличающуюся от собственных образов, которые значительно отличаются от традиционных Java-приложений, работающих на стандартной JVM. Отсутствие JIT-компилятора в собственных образах Substrate VM — это стратегический выбор, который помогает минимизировать общий размер исполняемого файла. Это связано с тем, что это устраняет необходимость включения JIT-компилятора и связанных с ним метаданных, которые являются значительными по размеру и сложности.

Кроме того, хотя GraalVM разработан с использованием Java, это накладывает определенные ограничения, особенно с точки зрения доступа к собственной памяти. Такие ограничения в первую очередь связаны с проблемами безопасности и необходимостью поддерживать совместимость между различными платформами. Однако доступ к собственной памяти необходим для оптимальных операций по сбору мусора. Для решения этой проблемы Substrate VM использует набор специализированных интерфейсов, которые обеспечивают безопасное и эффективное взаимодействие с собственной памятью. Эти интерфейсы являются частью более широкой архитектуры GraalVM и позволяют Substrate VM эффективно управлять памятью аналогично языкам более низкого уровня, таким как C, сохраняя при этом безопасность и управляемость Java.

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

К заслуживающим внимания элементам Substrate VM относятся:

  • Упрощенный доступ к памяти через такие интерфейсы, как Pointer Interface Pointer для необработанных операций с памятью и WordBase Interface WordBase для обработки значений размером в слово.

  • Разделение кучи на предварительно инициализированные сегменты, содержащие неизменяемые объекты, и сегменты времени выполнения для динамического распределения объектов (Рис. 5).

Memory Management in GraalVM Native Image

Рис. 5. Управление памятью в собственном образе

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

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

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

Такое разделение между предварительно инициализированной кучей бессмертных изображений и динамически управляемой кучей Java позволяет Substrate VM оптимизировать использование памяти и эффективность сборки мусора, удовлетворяя как статические, так и динамические аспекты требований к памяти приложения.

Куча чанка

В модели кучи Substrate VM память систематически организована в структуры, известные как фрагменты кучи. Эти фрагменты, размер которых по умолчанию обычно составляет 1024 КБ, образуют непрерывный сегмент виртуальной памяти, который выделяется исключительно для объектного хранилища. Организационная структура этих блоков представляет собой связанный список, хвостовой фрагмент которого представляет собой последний добавленный сегмент. Такая модель
способствует эффективному распределению памяти и управлению объектами.

Эти фрагменты кучи подразделяются на два типа: выровненные и невыровненные. Выровненные фрагменты кучи способны непрерывно удерживать несколько объектов. Такое выравнивание позволяет упростить сопоставление
объекты в соответствующие родительские фрагменты кучи, что делает управление памятью более интуитивно понятным и эффективным. В сценариях, где необходимо продвижение объекта — обычно во время сборки мусора и
оптимизация памяти — объект перемещается из исходного места в родительском фрагменте кучи в целевой фрагмент кучи, расположенный в назначенном «старом пространстве». Эта миграция является частью стратегии управления кучей поколений, которая помогает оптимизировать процесс сборки мусора путем отделения молодых объектов от старых, тем самым уменьшая накладные расходы во время циклов сборки мусора.

Сборщики мусора в собственном образе

Нативный образ GraalVM поддерживает различные GC, адаптированные к различным потребностям:

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

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

  • Epsilon GC: Минималистичный сборщик, который обрабатывает выделение, но не имеет возможности восстановления. Лучше всего использовать для недолговечных приложений, где полное использование кучи предсказуемо.

Заключение

В заключение, Substrate VM эффективно оптимизирует управление памятью в GraalVM, внедряя передовые методы, такие как специализированная сборка мусора и структурированное управление кучей. Эти функции, в том числе фрагменты кучи и отдельные сегменты памяти для изображений и кучи Java, оптимизируют сбор мусора и повышают производительность приложений. Поскольку Substrate VM поддерживает множество языков программирования и компилирует их в эффективные собственные двоичные файлы, он демонстрирует, как современные среды JVM могут выйти за рамки традиционных границ и повысить эффективность выполнения и надежность в различных средах приложений. Этот подход устанавливает высокие стандарты для будущих разработок в области технологий виртуальных машин и развертывания приложений.

Заявление о выпуске Эта статья воспроизведена по адресу: https://dev.to/yanev/memory-management-in-graalvm-native-image-4nbe?1 Если есть какие-либо нарушения, пожалуйста, свяжитесь с [email protected], чтобы удалить ее.
Последний учебник Более>

Изучайте китайский

Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.

Copyright© 2022 湘ICP备2022001581号-3