Может кто-нибудь объяснить эту диаграмму о распределении плит?

10

Я пытаюсь понять, как работает Slab Allocation и почему он отличается или лучше, чем обычный пейджинг.

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

Некоторые вопросы:

  • Что представляют собой элементы размером 3 КБ и 7 КБ? Должны ли они быть связаны как-то? Почему они упакованы таким образом?
  • В столбце caches - это кеши серых или белых / синих в серых? Являются ли серые коробки пакетом с кешами?
  • Являются ли плиты просто синими коробками или целые «Физически смежные страницы» - это плиты?

Буду очень признателен за помощь. Спасибо!

Распределение плиты

CodyBugstein
источник

Ответы:

15

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

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

Страницы являются типичной «единицей» операций с памятью. Когда приложение пользовательского пространства выделяет память или отображает в памяти файл или что-то в этом роде, оно обычно получает кратное значение размера страницы компьютера. Есть заметные исключения; Windows использует 64 КБ в качестве единицы выделения виртуальной памяти независимо от размера страницы ЦП. Тем не менее, давайте подумаем об этом так.

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

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

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

Так, например, объект, который представляет учетные данные безопасности процесса (скажем, идентификатор пользователя и идентификатор группы в POSIX, скажем), может быть только 16 байтов или около того, тогда как «процесс» или «поток» может быть до 1 КБ в размере. Очевидно, что вы не хотите использовать целую страницу для этих небольших записей, поэтому идея состоит в том, чтобы реализовать распределитель поверх страниц.

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

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

Другие структуры данных могут быть перенесены на диск, если не хватает памяти, и они вам скоро не понадобятся. Но вы не хотите делать это со структурами данных, которые управляют обменом или системой виртуальной памяти!

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

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

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

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

Что вы в основном делаете, так это позволяете каждому типу объекта иметь свой собственный распределитель, который можно настроить для нужд этого объекта. Эти распределители на объект называются «кэшами». Вы выделяете один кэш для каждого типа объекта. (Да, вы, как правило, также реализуете «кеш кэшей».) Каждый кеш хранит только объекты одного типа (например, только структуры потоков или только структуры адресного пространства).

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

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

Хорошая вещь о распределении slab состоит в том, что все эти параметры политики выделения (а также семантика памяти) могут быть настроены для каждого типа объекта. Некоторые кэши могут содержать пул пустых блоков, а некоторые нет. Некоторые могут быть перенесены на вторичное хранилище, а некоторые нет.

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

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

Некоторые объекты в Solaris требуют сложного и дорогостоящего строительства и уничтожения (например, объекты, которые имеют блокировку ядра), и поэтому они могут быть «частично свободными» (то есть построены, но не выделены). Solaris также оптимизирует бесплатное распределение слэба, поддерживая свободные списки для каждого процессора, гарантируя, что некоторые операции полностью не требуют ожидания.

Для поддержки общего назначения (например, для массивов, размер которых неизвестен во время компиляции), большинство операционных систем типа макроядра также имеют кэши, которые представляют размеры объектов, а не типы объектов . Например, FreeBSD поддерживает кэши для неизвестных объектов, размеры которых составляют степени 2 байтов, от 4 до 256.

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

Надеюсь, это поможет. Дайте мне знать, если что-то нужно уточнить.

Псевдоним
источник
6

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

Алгоритм выделения slab предоставляет запасы областей памяти, размеры и инициализация которых оптимизированы для этих стандартных структур данных. Например, как видно из рисунка, могут существовать объекты размером 3 КБ, а также объекты размером 7 КБ. Однако мы знаем, что ядро ​​выделяет память только в кратных размерах страницы.

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

Подводя итог, можно заметить, что на рисунке представлены примеры объектов, которые ОС знает как 3-7, независимо от размера в КБ. Ядро не выделяет памяти страниц специально для них, поскольку это экспоненциально увеличивает фрагментацию памяти, но «перенаправляет» их в кеш (серый прямоугольник). В кеше должны быть адреса, которые указывают физически смежные области памяти, плиты (белые / синие наборы ящиков) и объекты, наконец, выделяются в области плиты (часть, которая окрашена в синий цвет, среди свободных от полные аналогичные области памяти одной и той же плиты).

Джулия Фраскария
источник