Выделение памяти для общих программ
Прежде чем говорить о распределении памяти в Golang, давайте взглянем на распределение памяти в общих программах:
Выше приведена логическая классификация памяти программ.
Давайте посмотрим на реальную (настоящую логическую) карту памяти общей программы:
Основная идея Go о распределении памяти
Go — это язык программирования со встроенной средой выполнения (runtime).Язык программирования со встроенной средой выполнения обычно отказывается от традиционного метода выделения памяти и управляет ею сам. Таким образом, можно выполнять такие операции, как предварительное выделение и создание пула памяти, чтобы избежать проблем с производительностью, вызванных системными вызовами, и предотвратить необходимость системных вызовов при каждом выделении памяти.
Основную идею выделения памяти в Go можно разделить на следующие пункты:
- Каждый раз, когда у операционной системы запрашивается большой кусок памяти, Go выделяет этот кусок памяти, чтобы уменьшить количество системных вызовов.
- Алгоритм распределения памяти принимает Google
TCMalloc算法
. Алгоритм более сложный, и с принципом можно ознакомиться самостоятельно. Основная идея состоит в том, чтобы разделить память на очень маленькие части и разделить ее на многоуровневое управление, чтобы уменьшить гранулярность блокировок. - Когда объектная память освобождается, она на самом деле не освобождается, а помещается обратно в предварительно выделенный большой блок памяти для повторного использования. Только когда память слишком простаивает, она попытается вернуть часть памяти операционной системе, чтобы уменьшить общие накладные расходы.
Структура памяти Go
Go выделяет непрерывный участок памяти (виртуальную память) при запуске программы. В целом так:
Размер диапазона и растрового изображения на рисунке будет меняться по мере изменения кучи.
arena
Площадь арены — это то, что мы обычно называем кучей. В куче существует два типа «вещей» в соответствии с двумя измерениями управления и использования:
Один тип представляет собой большой блок памяти, состоящий из нескольких последовательных страниц с точки зрения распределения управления:
Другой тип с точки зрения использования, который мы обычно знаем: в куче много «объектов»:spans
Область промежутков может рассматриваться как область, используемая для арены распределения управления (т. е. кучи), упомянутой выше.
Эта область занимаетmspan
указатель,mspan
Что есть, обсудим позже.
Область промежутков используется для указания, какая страница (страница) в области арены принадлежитmspan
.
mspan
Можно сказать, что это самая основная единица управления памятью в go, но использование памяти все же должно основываться на «объектах».mspan
Какая связь с объектом?
На самом деле, «объект» также должен быть помещен вpage
в конце концовpage
Это основная единица хранения памяти.
Отложим проблему и посмотрим на выделение объектов и памяти в целом: как показано ниже
Если вы перераспределите «p4», не хватит ли памяти для выделения? Мусора много?
Эта общая ситуация с выделением вызовет фрагментацию памяти, как ее решить?
Он сводится к четырем словам: назначать по требованию. Go делит блоки памяти на 67 типов разного размера, а затем последовательно делит эти 67 типов больших блоков памяти на маленькие блоки (что можно приблизительно понимать как эквивалент разных размеров.page
) называетсяspan
(непрерывноpage
), который упоминается выше на языке gomspan
.
span
, таким образом решается проблема фрагментации.
Комментарии кода span разных размеров в 67 выглядят следующим образом (текущая версия 1.11):
// class bytes/obj bytes/span objects tail waste max waste
// 1 8 8192 1024 0 87.50%
// 2 16 8192 512 0 43.75%
// 3 32 8192 256 0 46.88%
// 4 48 8192 170 32 31.52%
// 5 64 8192 128 0 23.44%
// 6 80 8192 102 32 19.07%
// 7 96 8192 85 32 15.95%
// 8 112 8192 73 16 13.56%
// 9 128 8192 64 0 11.72%
// 10 144 8192 56 128 11.82%
// 11 160 8192 51 32 9.73%
// 12 176 8192 46 96 9.59%
// 13 192 8192 42 128 9.25%
// 14 208 8192 39 80 8.12%
// 15 224 8192 36 128 8.15%
// 16 240 8192 34 32 6.62%
// 17 256 8192 32 0 5.86%
// 18 288 8192 28 128 12.16%
// 19 320 8192 25 192 11.80%
// 20 352 8192 23 96 9.88%
// 21 384 8192 21 128 9.51%
// 22 416 8192 19 288 10.71%
// 23 448 8192 18 128 8.37%
// 24 480 8192 17 32 6.82%
// 25 512 8192 16 0 6.05%
// 26 576 8192 14 128 12.33%
// 27 640 8192 12 512 15.48%
// 28 704 8192 11 448 13.93%
// 29 768 8192 10 512 13.94%
// 30 896 8192 9 128 15.52%
// 31 1024 8192 8 0 12.40%
// 32 1152 8192 7 128 12.41%
// 33 1280 8192 6 512 15.55%
// 34 1408 16384 11 896 14.00%
// 35 1536 8192 5 512 14.00%
// 36 1792 16384 9 256 15.57%
// 37 2048 8192 4 0 12.45%
// 38 2304 16384 7 256 12.46%
// 39 2688 8192 3 128 15.59%
// 40 3072 24576 8 0 12.47%
// 41 3200 16384 5 384 6.22%
// 42 3456 24576 7 384 8.83%
// 43 4096 8192 2 0 15.60%
// 44 4864 24576 5 256 16.65%
// 45 5376 16384 3 256 10.92%
// 46 6144 24576 4 0 12.48%
// 47 6528 32768 5 128 6.23%
// 48 6784 40960 6 256 4.36%
// 49 6912 49152 7 768 3.37%
// 50 8192 8192 1 0 15.61%
// 51 9472 57344 6 512 14.28%
// 52 9728 49152 5 512 3.64%
// 53 10240 40960 4 0 4.99%
// 54 10880 32768 3 128 6.24%
// 55 12288 24576 2 0 11.45%
// 56 13568 40960 3 256 9.99%
// 57 14336 57344 4 0 5.35%
// 58 16384 16384 1 0 12.49%
// 59 18432 73728 4 0 11.11%
// 60 19072 57344 3 128 3.57%
// 61 20480 40960 2 0 6.87%
// 62 21760 65536 3 256 6.25%
// 63 24576 24576 1 0 11.45%
// 64 27264 81920 3 128 10.00%
// 65 28672 57344 2 0 4.91%
// 66 32768 32768 1 0 12.50%
Скажите, что представляет каждый столбец:
- класс: идентификатор класса, в каждой структуре диапазона есть идентификатор класса, указывающий тип объектов, которые может обрабатывать диапазон.
- bytes/obj: этот класс представляет количество байтов объекта
- bytes/span: количество байтов, которое каждый диапазон занимает в куче, то есть количество страниц * размер страницы.
- объекты: количество объектов, которые могут быть выделены на интервал, то есть (байты/промежутки)/(байты/объект)
- ненужные байты: Фрагментация памяти, создаваемая каждым интервалом, то есть (байты/промежутки)% (байты/объект)
Читайте следующим образом: В качестве примера возьмем span, тип (класс) которого равен 1, размер элемента в span равен 8 байт, сам span занимает 1 страницу, то есть 8K, и всего можно сохранить 1024 объекта.
Внимательные школьники могут обнаружить, что всего существует 66 типов кодов, а также есть специальный диапазон: То есть при появлении объекта размером более 32к будет выделен специальный спан прямо из кучи.Тип (класс) этого специального спана равен 0, и включается только один большой объект.Размер спана определяется размер объекта.
bitmap
Существует несколько видов растровых изображений: растровые изображения стека, данных и bss, и именно об этом я собираюсь поговорить в этот раз.heap bitmaps
.
Роль растрового изображения в этом состоит в том, чтобы отметить меткуarena
(т.е. куча) объектов. Один должен отметить, есть ли объект по соответствующему адресу, а другой — отметить, был ли объект помечен gc. Функция немного, поэтому,heap bitmaps
Используйте два бита.
Один байт в области растрового изображения соответствует структуре памяти четырех указателей в области арены следующим образом:
Адрес растрового изображения увеличивается от старшего адреса к младшему адресу.
Макро картинка такая:
Основная функция растрового изображения — служить сборщику мусора.arena
Он содержит базовую единицу управления и объекты или сущности, генерируемые при запуске программы.Эти две части соответственноspans
иbitmap
Эти две области без кучи соответствуют памяти.
Логическая схема выглядит следующим образом:
Компонент управления памятью
Компоненты управления памятью Go в основном включают:mspan
,mcache
,mcentral
иmheap
-
mspan
Базовая единица управления памятью, в которой непосредственно хранятся данные. -
mcache
: горутина, привязанная к каждой горутине времени выполнения.mcache
(В частности, это P в связанной модели параллелизма GMP, поэтому его можно выделить без блокировок.mspan
, о чем будет сказано позже),mcache
выделит пространство памяти, необходимое горутине для запуска (т.е.mspan
). -
mcentral
для всехmcache
вырезать резервную копиюmspan
-
mheap
Представляет все пространство кучи, занимаемое программой Go. Он также управляет интервалами бездействия и при необходимости запрашивает новую память у операционной системы.
mspan
Некоторые спросят: где хранится структура mspan? На самом деле память самой структуры mspan выделяется из системы, поэтому я не буду здесь ее слишком подробно обсуждать.mspan
сказано вышеspans
Когда я конкретно упомянул об этом, удобно выделять и использовать блоки памяти в соответствии с размером объекта.Всего их 67 типов, самое главное решить проблему фрагментации памяти, что уменьшает фрагментацию памяти и улучшает использование памяти.mspan
Представляет собой двусвязный список, основные свойства которого показаны на следующем рисунке:
mspan
это базовая единица управления памятью в go, см. вышеspans
На самом деле подробное объяснение было сделано в этой статье, поэтому я не буду повторяться здесь.
mcache
Чтобы избежать непрерывной блокировки, когда несколько потоков обращаются к памяти, горутина выделяетspan
Кэш блоков памяти, этот кешmcache
, к которому будет привязана каждая горутинаmcache
, нет конкуренции блокировок, когда каждая горутина обращается за памятью.
Как?
Прежде чем говорить, ознакомьтесь с моделью параллельного планирования Go.Если вы еще не знакомы с ней, прочитайте мою статью.Tickets.WeChat.QQ.com/Yes/74, включая BRT Q2T…
Тогда посмотрите на изображение ниже:
В основном это выглядит как на картинке выше. Взгляните на нашуmcache
где это находится? Прямо на П!
Знайте, почему нет конкуренции блокировок, потому что горутина может быть связана только с одним P во время работы, иmcache
Как раз на P, поэтому не может быть конфликта блокировок.
Посмотрим еще разmcache
Конкретная структура:
Связанный список span в mcache разделен на две группы, одна группа содержит объекты типа указателя, а другая группа — это объекты, не содержащие типа указателя. Почему отдельно?
Это в основном для облегчения GC.Когда выполняется сборка мусора, нет необходимости дополнительно сканировать список объектов, которые не содержат указатели, чтобы увидеть, есть ли ссылки на другие активные объекты (если вы мало знаете о сборщике мусора go, пожалуйста, см. мою статью.Tickets.WeChat.QQ.com/Yes/_Return 0-8 номер 5…).
за<=32k
объект, который будет передан непосредственно черезmcache
распространять.
Здесь, я думаю, необходимо рассказать о классификации предметов в го по размерному измерению. Делится на три категории:
- жестяные выделения (размер
- small allocations (16 bytes < size <= 32k)
- large allocations (size > 32k)
Первые две категории:tiny allocations
иsmall allocations
непосредственно черезmcache
быть выделенным.
заtiny allocations
раздача, есть микродозаторtiny allocator
Для выделения выделенные объекты не содержат указателей, таких как некоторые небольшие строки и независимые escape-переменные, не содержащие указателей.
small allocations
распределениеmcache
В соответствии с размером объекта, чтобы найти размер собственного существования, чтобы соответствоватьmspan
выделить.
когдаmcach
Когда нет свободного места,mcentral
изmspans
Список, чтобы получить новую спецификацию желаемого размераmspan
.
mcentral
для всехmcache
предоставить нарезанныйmspan
.
каждыйmcentral
сохранить определенный тип глобальногоmspan
Список, как назначенных, так и неназначенных.
все еще помнюmspan
из 67 типов? Сколько типов естьmspan
Как многоmcentral
.
каждыйmcentral
будет содержать обаmspan
Список:
- нет свободных объектов или
mspan
Былmcache
кэшированныйmspan
Список (пустой mspanList) - с бесплатными объектами
mspan
Список (пустой mspanList)
так какmspan
является глобальным и будет использоваться всемиmcache
доступ, поэтому будут проблемы с параллелизмом, поэтомуmcentral
Будет замок.
не замужемmcentral
Структура выглядит следующим образом:
Если вам нужно выделить память,mcentral
нет свободного времениmspan
список, вам нужноmheap
получить.
mheap
mheap
Его можно представить как все пространство кучи, занимаемое программой Go.mheap
Глобально уникальная, она может рассматриваться как глобальная переменная.
Его структура выглядит следующим образом:
mheap
В дополнение к вышеупомянутомуmcache
все кромеmcache
Он существует в модели планирования P of Go GMP, о которой упоминалось выше.Чтобы узнать о модели параллелизма GMP, вы можете обратиться к моей статье.Tickets.WeChat.QQ.com/Yes/74, включая BRT Q2T…Если присмотреться, то можно найтиmheap
В замке тоже есть замок. Какова функция этого замка?
Мы знаем, что объекты размером более 32 КБ определяются как большие объекты непосредственно черезmheap
распространять. Заявки на эти крупные объекты делаютсяmcache
выпущено, иmcache
На P во время работы программы часто бывает несколько P. Следовательно, это приложение памяти является параллельным, поэтому для обеспечения потокобезопасности должна быть глобальная блокировка.
Если требуется выделенная память,mheap
Если страниц больше нет, то обратиться к операционной системе за новой серией страниц (минимум 1Мб).
Краткое описание процесса выделения памяти Go
Существует три типа объектов:
- крошечные объекты, размер
- Общие небольшие объекты, 16 байт
- Размер большого объекта > 32 КБ
Существует три метода распространения:
- крошечные выделения (размер
- малые выделения (размер
- большие выделения (размер > 32 КБ) выделения больших объектов, передать напрямую
mheap
распространять. Применение этих больших объектов осуществляется за счет глобальной блокировки, поэтому только один P может подать заявку на это в любой момент времени.
Распределение объекта:
- Объекты, размер которых находится в диапазоне ( size mcacheраспределение микродозатором на
- Диапазон размеров (0
- Диапазон размеров (16B
- диапазон размеров в (размер > 32 КБ): выделение больших объектов
Порядок распределения:
- Во-первых, рассчитав используемую спецификацию размера.
- затем используйте
mcache
Выделение блока в соответствующей спецификации размера. - если
mcentral
нет доступных блоковmheap
Подать заявку и найти наиболее подходящий по алгоритмуmspan
. - Если подать заявку на
mspan
Если размер приложения превышен, оно будет разделено в соответствии с потребностями, чтобы вернуть количество страниц, требуемое пользователем. Остальные страницы образуют новый mspan, который возвращается в список свободных mheap. - Если в mheap нет доступных диапазонов, запросите новый набор страниц (минимум 1 МБ) из операционной системы.
Управление памятью в Go очень сложное, и каждая версия имеет небольшие изменения. Здесь я говорю только о вещах, которые легче всего понять макроскопически. Надеюсь, вы выскажете больше мнений. Если у вас есть какие-либо вопросы, пожалуйста, свяжитесь со мной вовремя. Вот контактные данные:
Пожалуйста, обратите внимание на мой публичный аккаунт WeChat互联网技术窝
Вопросы можно оставлять прямо в паблике
использованная литература:
- Распределение программ в памятиБлог Woo Woo.cn на.com/Lynn-Zhang/…
- Начните с выделения памятиБилеты.WeChat.QQ.com/Yes/E-W KF Ru1 маленький…
- Перевод: наглядное руководство по распределителю памяти Gowoohoo.linuxhow.com/go-memory-ahhh…
- Графическое выделение памяти Gonuggets.capable/post/684490…
- Изучение исходного кода Golang (3) Принцип реализации GCБлог Woo Woo.cn на.com/ZK Web/Fear/788…
- Простая и понятная интерпретация принципа распределения памяти в GoОсобенно Aliyun.com/articles/65…
- Дождевые метки >
- перейти к распределению памяти (англ.)Андре STC.com/post/go-what...