Очередной осенний рекрутинговый сезон. О Боже, меня так сильно оскорбили~ Нет, я не обновлял свой блог после того, как исчез несколько дней назад. На самом деле, я тайно проводил время, просматривая учебники (туман
Давно делюсь блогами в сообществе.Потому что в прошлых статьях много упущений,много больших парней прокомментировали и указали на мои недостатки.Я очень рада и разочарована.Я рада,что все помогли мне указать мои ошибки Я разочарован Небольшие знания никогда не могут быть совершенными. Одним словом, приветствую все виды пиара в комментариях~
Хорошо, вернемся к теме. Когда делал обзор случайно увидел актуальные познания виртуалки java, и очень заинтересовался, сегодня буду совмещатьмодель памяти компьютерасоответствующие знания иМодель памяти Java,Объектная модель Java,Структура памяти JVMИ другие сопутствующие знания, связанные последовательно, в этой статье всего 1,5 Вт слов, поделитесь ею со всеми, спасибо за чтение.
Хотите разблокировать больше новых поз? Пожалуйста, посетите мой личный блог https://blog.tengshe789.tech/ (😘
память компьютера
Я считаю, что у каждого есть компьютер, а также есть опыт сборки компьютера своими руками. Теперь мощный самодельный компьютер можно собрать примерно за 3k, процессор i5-8400 — 869 юаней, память DDR4 — 1200 юаней, материнская плата b360 — 300 юаней, радиатор — 50 юаней, механический жесткий диск — 200 юаней, блок питания 350 Вт — 300 юаней, шасси — 100 юаней. можно получить мощный компьютер 6C6T всего за 3k.
Что самое главное в ПК? Если вы посмотрите на цену, вы поймете, что это процессор и память.Позвольте мне представить взаимосвязь между процессором и памятью.
ЦП и кэш-память неразрывно связаны
термины, связанные с процессором
Во-первых, позвольте мне объяснить соответствующую терминологию процессора:
- сокет: слот, в который процессор вставляется в материнскую плату, и процессор называются сокетом.
- Die: Ядро (Die), также известное как ядро, является одним из физических компонентов процессора. Процессор также будет разделен на многокристальный процессор и однокристальный процессор.Например, наш нынешний мощный процессор AMD TR-2990WX представляет собой 4-процессорный процессор, и каждый кристалл имеет 8 ядер (ядра).
- ядро: то есть физическое ядро. Слово «ядро» было придумано Intel, изначально оно использовалось для того, чтобы отличить его от конкурента AMD, а позже оно использовалось все реже.
- thread: количество аппаратных потоков. Выполнение программы может потребовать одновременного выполнения нескольких потоков ~ и сейчас существует относительно мощная технология гиперпоточности. Раньше ядро ЦП часто поддерживало только один поток. Теперь некоторые мощные ЦП, такие как IBM POWER 9 , поддержка 8 Ядро имеет 32 потока (в среднем 4 потока на ядро), и теоретическая производительность очень высока.
Подводя итог, принимая звездный процессор AMD TR-2990WX за каштан, этот процессор использует сокет, а в сокете 4 кристалла, всего 32 физических ядра и 64 потока.
кэш процессора
Мы все знаем, что данные, которые должен обрабатывать процессор, будут храниться в памяти, но почему это так?
Ответ, конечно, нет. Скорость обработки процессора очень высока.Хотя скорость памяти очень высока, она вообще не может идти в ногу с темпами процессора.Поэтому появляется кеш. В отличие от памяти из семейства DRAM, самые большие особенности кэш-памяти SRAM и памяти заключаются в том, что они особенно быстрые, имеют небольшую емкость, сложную структуру и высокую стоимость.
Основные причины разницы в производительности памяти и кэша следующие:
- Для DRAM требуется только один конденсатор и один транзистор для хранения одного бита данных, а для SRAM требуется шесть транзисторов. Поскольку данные, хранящиеся в DRAM, фактически находятся в конденсаторе, конденсатор необходимо заряжать и разряжать для выполнения операций чтения и записи, что приводит к относительно большой задержке чтения и записи данных.
- Хранилище можно принять за двумерный массив, где каждая ячейка памяти имеет свой адрес строки и адрес столбца. Емкость SRAM очень мала, а ее единица хранения относительно короткая (короткие строки и столбцы), которые могут быть переданы в SRAM за один раз, в то время как DRAM необходимо передавать адреса строк и столбцов отдельно.
- Частота SRAM относительно близка к частоте процессора, в то время как частота DRAM сильно отличается от частоты процессора.
Современный кеш обычно интегрируется в ЦП.Чтобы удовлетворить потребности в производительности и стоимости, реальный кеш часто использует многоуровневую архитектуру кеша пирамидального типа. этоКогда ЦП хочет прочитать часть данных, он сначала ищет в кеше L1, если он не найден, он ищет в кеше L2, и если он все еще не находит, он ищет в кеше L3 или объем памяти.
Ниже приведена архитектура Skylake первого поколения, которую недавно использовала Intel.
Как видите, каждое ядро имеет свои собственные кэши L1 и L2, и они совместно используют кеш L3. Если процессор хочет получить доступ к данным в памяти, он должен пройти через четырехуровневый кэш L1, L2, L3, LLC (или L4).
проблемы с когерентностью кэша
В начале процессор был фактически только одним ядром и одним потоком, тогда вообще не было необходимости рассматривать проблему когерентности кэша.один поток, то есть доступ к кешу ядра процессора осуществляется только одним потоком. Кэш эксклюзивный, и конфликтов доступа и прочих проблем не будет.
Позже в поле нашего зрения попала технология гиперпоточности,''Многопоточность одноядерного процессора'', то есть несколько потоков в процессе будут получать доступ к общим данным в процессе одновременно.После того, как ЦП загрузит определенный участок памяти в кеш, когда разные потоки обращаются к одному и тому же физическому адресу, они будут сопоставлены с то же расположение кеша. Переключение потоков, кеш по-прежнему не будет аннулирован. Но поскольку в любой момент времени может выполняться только один поток, нарушение доступа к кешу отсутствует.
С непрерывным развитием времени пришла **«многопоточность многоядерного процессора»**, то есть несколько потоков обращаются к общей памяти в процессе, и эти несколько потоков выполняются на разных ядрах, затем каждое ядро будет находиться в собственном буфере разделяемой памяти, зарезервированном в caehe. Поскольку несколько ядер могут быть распараллелены, несколько потоков могут одновременно записывать в свои соответствующие кэши, и данные между соответствующими кэшами могут быть разными.
это то, что мы говоримкогерентность кэшапроблема.
В настоящее время признанным лучшим решением является Intelпротокол МЭСИ, на котором мы сосредоточимся ниже.
протокол МЭСИ
Прежде всего, давайте поговорим о единице операции ввода-вывода.Большинство людей знает, что операция ввода-вывода в памяти осуществляется не в байтах, а в «блоках».Почему?
На самом деле это связано с тем, что доступ к данным операции ввода-вывода имеет характеристики пространственной непрерывности, то есть требуется доступ к большому количеству данных в пространстве памяти, но операция ввода-вывода относительно медленная, и время чтения одного байта и чтения N байтов в основном одинаково.
Smart Intel предусматривает, что наименьшая единица хранения в кеше процессорастрока кэшаcache line
, в процессоре x86, acache line
Хранит 64 байта, каждый уровень кеша разбит на множество группcache line
.
Посмотрите, как работает кеш 👉Википедия
Далее давайте посмотрим на спецификацию MESI, которая на самом деле названа в честь четырех состояний строки кэша.Мы определяем, что каждая строка кэша в ЦП помечается 4 состояниями (представленными двумя дополнительными битами (битами)), а именно:
-
М: изменено
Кэш-строка кэшируется только в кэш-памяти ЦП, и является грязной, то есть несовместимой с данными в основной памяти, память в кэш-строке должна быть сохранена в определенный момент в будущем (что позволяет другим ЦП до чтение соответствующей памяти в основной памяти) запись обратно в основную память. После записи обратно в основную память состояние строки кэша становится монопольным.
-
Е: Эксклюзив
Строка кеша кэшируется только в кеше ЦП, она неизменна (чиста) и согласуется с данными в основной памяти. Это состояние может стать общим в любой момент, когда другие процессоры читают память. Аналогичным образом, когда ЦП изменяет содержимое строки кэша, состояние может стать измененным.
-
S: Общий (общий)
Это состояние означает, что строка кэша может кэшироваться несколькими процессорами, и данные в каждом кэше согласуются с данными основной памяти (чистые).Когда один процессор изменяет строку кэша, строка кэша в других процессорах может быть недействительной (изменена ) в недопустимое состояние (Invalid).
-
Я: неверный
Кэш недействителен (какой-то другой ЦП мог изменить строку кэша).
Однако наличие этих четырех состояний также может вызвать определенные проблемы. Вот цитата из оракулаДокументация.
Одновременное обновление одного элемента в одной и той же кэшированной строке кода с разных процессоров делает недействительной всю кэшированную строку кода, даже если обновления логически независимы друг от друга. Каждый раз, когда обновляется один элемент кэшированной строки кода, эта строка кода помечается какнедействителен. Другие процессоры, обращающиеся к другим элементам в той же строке кода, увидят эту строку кода, помеченную какнедействителен. Заставляет их извлекать более новую копию строки кода из памяти или из другого места, даже если элементы, к которым осуществляется доступ, не были изменены. Это связано с тем, что когерентность кэша поддерживается на основе кэшированных строк кода, а не на основе отдельных элементов. В результате будет увеличиваться межсетевое взаимодействие и накладные расходы. Кроме того, пока выполняется обновление кэшированной строки кода, доступ к элементам в этой строке кода запрещен.
Протокол MESI может гарантировать согласованность кэша, но не может гарантировать производительность в реальном времени.Эта ситуация называетсяложный обмен.
проблема ложного обмена
Проблема ложного совместного использования на самом деле является реальной проблемой в Java. Предположим, что есть класс Java, подобный следующему
class MyObiect{
long a;
long b;
long c;
}
Согласно спецификации Java, объект MyObiect размещается в пространстве кучи, три переменные a, b и c являются соседями в пространстве памяти, занимая соответственно 8 байт, а сумма длин составляет 24 байта. И наша строка кэша x86 составляет 64 байта, вполне возможно, что эти три переменные будут в одной строке кэша и разделены двумя разными ядрами процессора!
В соответствии с протоколом MESI, если поток 1 и поток 2 в разных физических ядрах ЦП взаимодействуют с этими переменными взаимоисключающим образом, весьма вероятно, что они вытеснят ресурсы друг друга, в результате чего первоначальный параллельный процесс станет последовательным, что значительно упростит работу системы. производительность Параллелизм, это ложное совместное использование кешей.
Решить ложный обмен
На самом деле решить ложное совместное использование очень просто, достаточно поместить эти переменные в разные строки кеша. В java8 предусмотрено универсальное решение, то есть использование@Contended
Аннотация, чтобы гарантировать, что переменные или свойства в объекте не находятся в строке кеша~
@Contended
class VolatileObiect{
volatile long a = 1L;
volatile long b = 2L;
volatile long c = 3L;
}
проблема с несогласованностью памяти
Выше я сказал, что протокол MESI решает проблему когерентности кэша в многоядерных процессорах, теперь поговорим о несогласованности памяти процессоров.
Три архитектуры ЦП
Во-первых, нужно понять три существительных:
- SMP(Symmetric Multi-Processor)
SMP, в симметричной многопроцессорной системе много тесно связанных мультипроцессоров.В такой системе все ЦП совместно используют все ресурсы, такие как шины, память, системы ввода-вывода и т. д., и существует только одна копия операционной системы или управление базой данных.Одной из самых больших особенностей этой системы является то, что все ресурсы являются общими. Нет никакой разницы между несколькими процессорами, доступом к памяти, периферийным устройствам, операционной системе в равной степени. Операционная система управляет очередью, и каждый процессор, в свою очередь, обрабатывает процессы в очереди. Если два процессора одновременно запрашивают доступ к ресурсу (например, к одному и тому же адресу памяти), аппаратный и программный механизм блокировки используется для решения проблемы конфликта ресурсов.
[
Так называемая симметричная многопроцессорная структура относится к симметричной работе нескольких ЦП на сервере без отношения первичных, вторичных или подчиненных. Каждый ЦП совместно использует одну и ту же физическую память, и время, необходимое каждому ЦП для доступа к любому адресу в памяти, одинаково, поэтому SMP также известен как согласованная структура доступа к памяти (UMA: унифицированный доступ к памяти). Способы расширения SMP-сервера включают увеличение памяти, использование более быстрых ЦП, увеличение ЦП, расширение ввода-вывода (слоты и шины) и добавление дополнительных внешних устройств (обычно дискового хранилища).
Главной особенностью SMP-сервера является совместное использование всех ресурсов (процессор, память, ввод-вывод и т. д.) в системе. Именно из-за этой характеристики основная проблема SMP-серверов заключается в том, что они имеют очень ограниченную масштабируемость. Для SMP-сервера каждая общая ссылка может стать узким местом при расширении SMP-сервера, и самым ограниченным является память. Поскольку каждый ЦП должен получать доступ к одним и тем же ресурсам памяти через одну и ту же шину памяти, по мере увеличения числа ЦП конфликты доступа к памяти будут быстро увеличиваться, что в конечном итоге приведет к растрате ресурсов ЦП и значительно снизит эффективность производительности ЦП. Эксперименты показывают, что наилучший вариант использования ЦП сервера SMP — от 2 до 4 ЦП.
[
- NUMA(Non-Uniform Memory Access)
Из-за ограниченности возможностей SMP по расширению люди начали искать способы эффективного расширения технологии для создания крупномасштабных систем. NUMA — один из результатов этих усилий. Используя технологию NUMA, в сервере можно объединить десятки (или даже сотни) процессоров. Структура модуля ЦП сервера NUMA показана на рисунке:
Основная функция сервера NUMA состоит в том, чтобы иметь несколько модулей ЦП, каждый модуль ЦП состоит из нескольких ЦП (например, 4) и имеет независимую локальную память, слоты ввода-вывода и т. д. Поскольку его узлы могут подключаться и обмениваться информацией через соединительные модули (такие как Crossbar Switch), каждый ЦП может получить доступ к памяти всей системы (это важное различие между системами NUMA и системами MPP). Очевидно, что скорость обращения к локальной памяти будет намного выше, чем скорость обращения к удаленной памяти (памяти других узлов в системе), поэтому неоднородное хранилище обращается к NUMA. Благодаря этой особенности, чтобы лучше использовать производительность системы, необходимо свести к минимуму информационное взаимодействие между различными модулями ЦП при разработке приложений.
Использование технологии NUMA может лучше решить проблему расширения исходной системы SMP и может поддерживать сотни ЦП на одном физическом сервере. Примеры типичных серверов NUMA включают HP Superdome, SUN15K, IBMp690 и т. д.
Однако у технологии NUMA есть и определенные недостатки.Поскольку латентность доступа к удаленной памяти намного больше, чем у локальной памяти, при увеличении числа процессоров производительность системы не может увеличиваться линейно. Например, когда HP выпустила сервер Superdome, она объявила его относительную производительность по сравнению с другими серверами HP UNIX.Было обнаружено, что относительная производительность 64-процессорного Superdome (структура NUMA) составляла 20, а 8-процессорного N4000. (общая структура SMP) имеет относительное значение производительности 20. ) имеет относительное значение производительности 6,3. Из этого результата мы видим, что 8-кратное увеличение количества процессоров означает только 3-кратное повышение производительности.
- MPP(Massive Parallel Processing)
В отличие от NUMA, MPP предоставляет другой способ расширения системы.Он состоит из нескольких SMP-серверов, соединенных через определенную сеть взаимосвязи узлов для совместной работы для выполнения одних и тех же задач.С точки зрения пользователя, это серверная система. Его основная особенность заключается в том, что он состоит из нескольких SMP-серверов (каждый SMP-сервер называется узлом), соединенных через сеть межузловых соединений, и каждый узел имеет доступ только к своим локальным ресурсам (памяти, хранилищу и т. д.), что полностью общая структура (Ничего не делиться). , поэтому возможность расширения является лучшей. Теоретически его расширение не ограничено. Текущая технология может реализовать взаимосвязь 512 узлов и тысяч ЦП. В настоящее время в отрасли нет стандарта для сети межузлового взаимодействия, такого как Bynet от NCR и SPSwitch от IBM, все они используют разные внутренние механизмы реализации. Но Интернет узла используется только внутри сервера MPP и прозрачен для пользователей.
В системе MPP каждый узел SMP также может запускать собственную операционную систему, базу данных и т. д. Но, в отличие от NUMA, у него нет проблемы с внешним доступом к памяти. Другими словами, центральный процессор каждого узла не может получить доступ к памяти другого узла. Обмен информацией между узлами осуществляется через сеть межузловых соединений, и этот процесс обычно называют перераспределением данных.
Но MPP-серверу нужен сложный механизм для планирования и балансировки нагрузки и параллельной обработки различных узлов. В настоящее время некоторые серверы, основанные на технологии MPP, часто скрывают эту сложность с помощью программного обеспечения системного уровня (например, баз данных). Например, Teradata от NCR представляет собой программное обеспечение реляционной базы данных, основанное на технологии MPP.При разработке приложений на основе этой базы данных, независимо от того, из скольких узлов состоит внутренний сервер, разработчики сталкиваются с одной и той же системой баз данных, не задумываясь о том, как запланировать нагрузку на некоторые из этих узлов.
MPP (Massively Parallel Processing), система массивно-параллельной обработки, такая система состоит из множества слабо связанных процессорных блоков, следует отметить, что здесь вместо процессора упоминается процессорный блок. ЦП в каждом блоке имеет свои собственные ресурсы, такие как шина, память, жесткий диск и т. д. В каждой ячейке есть копия экземпляра операционной системы и базы данных управления. Самая большая особенность этой структуры заключается в том, что она не разделяет ресурсы.
Когерентность кэша в структуре NUMA
Вы должны знать, что протокол MESI обеспечивает согласованность кеша в рамках традиционной структуры SMP.Чтобы добиться согласованности кеша в архитектуре NUMA, Intel представила протокол расширения MESI-MESIF, но в настоящее время нет информации, и нет способ изучить его. , для получения дополнительной информации, пожалуйста, обратитесь к вики Intel.
Модель памяти Java
причина
Почему мы должны учитывать модель памяти при написании программ?Как мы уже говорили ранее, проблема согласованности кэша и проблема согласованности памяти вызваны непрерывным обновлением оборудования. Самый простой и прямой способ решить проблему — отменить кэш ЦП и позволить ЦП напрямую взаимодействовать с основной памятью. Однако это может гарантировать проблемы параллелизма при многопоточности. Однако это немного назад.
Следовательно, чтобы обеспечить атомарность, видимость и упорядоченность в параллельном программировании. Есть важное понятие, а именно — модель памяти.
То есть для обеспечения корректности разделяемой памяти (видимость, упорядоченность, атомарность) требуется модель памяти для определения соответствующих спецификаций поведения операций чтения и записи многопоточных программ в системе разделяемой памяти~
JMM
Модель памяти Java переведена с английской модели памяти Java (JMM). На самом деле JMM не так реальна, как структура памяти JVM. ЭтоЭто механизм и спецификация, которые соответствуют спецификации модели памяти, скрывают различия в доступе для различных аппаратных средств и операционных систем, а также обеспечивают доступ программ Java к памяти на различных платформах.. Как описано в JSR-133: Модель памяти Java и спецификация потоков, JMM относится к многопоточности и описывает набор правил или спецификаций, определяющих запись потока в общую переменную, когда другой поток записывает в нее видимую информацию.
Итак, если подвести краткий итог, то многопоточность Java взаимодействует через разделяемую память, и из-за использования разделяемой памяти для обмена данными возникнет ряд проблем, таких как видимость, атомарность и последовательность в процессе обмена данными, а JMM It — это модель, построенная на основе многопоточной связи и ряда связанных с ней функций. JMM определяет набор грамматик, которые сопоставляются с языком Java, какvolatile
,synchronized
и другие ключевые слова.
В JMM мы называем общую память, которая взаимодействует между несколькими потоками, основной памятью, а в параллельном программировании несколько потоков поддерживают свою собственную локальную память (это абстрактное понятие), а хранимые данные — это копия данных основной памяти в . иJMM в основном контролирует взаимодействие данных между локальной памятью и основной памятью..
В Java JMM — очень важная концепция, и именно благодаря JMM параллельное программирование в Java позволяет избежать многих проблем.
JMM-приложение
Друзья, знакомые с многопоточностью Java, знают, что в Java предусмотрен ряд ключевых слов, связанных с параллельной обработкой, напримерvolatile
,synchronized
,final
,concurrent
пакет и т. д. На самом деле это некоторые ключевые слова, предоставленные нам моделью памяти Java после инкапсуляции базовой реализации.
При разработке многопоточного кода мы можем напрямую использоватьsynchronized
В ожидании ключевых слов для управления параллелизмом вам не нужно заботиться об оптимизации базового компилятора, согласованности кэша и других проблемах. так,В дополнение к определению набора спецификаций модель памяти Java также предоставляет ряд примитивов, которые инкапсулируют базовую реализацию для непосредственного использования разработчиками.
Чтобы решить проблемы атомарности, упорядоченности и видимости в параллельном программировании, давайте посмотрим, какие методы используются для обеспечения этого в Java.
атомарность
атомарностьЭто означает, что в операции процессор не может быть приостановлен в середине, а затем снова запланирован, операция не может быть прервана, или выполнение завершено, или оно не выполнено.
JMM гарантирует атомарность доступа к базовым типам данных (фактически запись переменной рабочей памяти в основную память делится на два основных этапа: сохранение и запись), но реальные сценарии бизнес-процессов часто требуют более широкого диапазона гарантий атомарности.
В Java для обеспечения атомарности предусмотрены две высокоуровневые инструкции байт-кода.monitorenter
иmonitorexit
, и эти два байт-кода соответствуют ключевым словам в Java:synchronized
.
Итак, в Java вы можете использоватьsynchronized
чтобы гарантировать атомарность операций внутри методов и блоков кода. Рекомендовать статью здесьГлубокое понимание принципа синхронизированной реализации параллелизма Java..
видимость
видимостьЭто означает, что когда несколько потоков обращаются к одной и той же переменной, один поток изменяет значение переменной, а другие потоки сразу же видят измененное значение.
Модель памяти Java реализована с опорой на основную память в качестве среды передачи путем синхронизации нового значения обратно в основную память после изменения переменной и обновления значения переменной из основной памяти до того, как переменная будет прочитана.
на Явеvolatile
Ключевое слово предоставляет функцию, т. е. измененная им переменная может быть синхронизирована сосновная память, измененные им переменные сбрасываются из основной памяти перед каждым использованием. Поэтому вы можете использоватьvolatile
Для обеспечения видимости переменных во время многопоточных операций.
Кромеvolatile
, на Явеsynchronized
иfinal
,static
Три ключевых слова также могут обеспечить видимость. Вот мои заметки о прочитанном:
упорядоченность
упорядоченностьТо есть порядок выполнения программы соответствует порядку выполнения кода.
В Java вы можете использоватьsynchronized
иvolatile
Для обеспечения упорядоченности операций между несколькими потоками. Реализация отличается:
volatile
Ключевое слово отключает перекомпоновку инструкций.synchronized
Ключевое слово гарантирует, что одновременно разрешена только одна операция потока.
Что ж, вот краткое введение в ключевые слова, которые можно использовать для решения проблемы атомарности, видимости и упорядочения в параллельном программировании на Java. Читатель мог заметить, что кажетсяsynchronized
Ключевое слово всемогуще, оно может одновременно удовлетворять трем вышеуказанным характеристикам, чем на самом деле злоупотребляют многие люди.synchronized
причина.
ноsynchronized
Это влияет на производительность.Хотя компилятор предоставляет множество методов оптимизации блокировок, не рекомендуется злоупотреблять ими.
JVM
Все мы знаем, что Java-код должен выполняться на виртуальной машине, а виртуальная машина будет делить управляемую память на несколько разных областей данных во время выполнения Java-программы, и эти области имеют свои собственные цели. Поговорим о структуре области оперативной памяти JVM.
Структура области памяти времени выполнения JVM
В «Спецификации виртуальной машины Java (Java SE 8)» структура области памяти времени выполнения JVM описывается следующим образом:
1.счетчик команд
Счетчик программ (регистр счетчика программ), также известный как регистр ПК. Друзья, которые, должно быть, изучили язык ассемблера, знакомы с концепцией счетчика программ.В языке ассемблера счетчик программ относится к регистру в ЦП, в котором хранится адрес инструкции, выполняемой в данный момент программой (можно также сказать, что сохранить адрес следующей инструкции, адрес блока памяти), когда ЦП необходимо выполнить инструкцию, ему необходимо получить адрес блока памяти, в котором инструкция должна быть выполнена в данный момент, из счетчика программ, и затем получить инструкцию по полученному адресу.После получения инструкции программный счетчик автоматически увеличится на 1 или получит адрес следующей инструкции по указателю передачи, и так далее, пока не будут выполнены все инструкции.
Хотя программный счетчик в JVM не является физическим и концептуальным регистром ЦП, как счетчик программ на языке ассемблера, функция счетчика программ в JVM логически эквивалентна функции счетчика программ на языке ассемблера, то есть Say is используется для указания того, какую команду следует выполнить.
Поскольку в JVM многопоточность получает время выполнения процессора за счет переключения потоков по очереди, поэтому в любой конкретный момент ядро процессора будет выполнять инструкции только в одном потоке, поэтому для того, чтобы сделать каждый поток в потоке после переключатель, положение выполнения программы перед переключением может быть восстановлено.Каждый поток должен иметь свой собственный независимый счетчик программ и не может мешать друг другу, в противном случае будет нарушен нормальный порядок выполнения программы. Так что, так сказать, счетчик программ является приватным для каждого потока.
В спецификации JVM, если поток выполняет не нативный метод, в программном счетчике хранится адрес инструкции, которую нужно выполнить в данный момент; если поток выполняет нативный метод, значение в программном счетчике не определено.
Поскольку размер пространства, занимаемого данными, хранящимися в программном счетчике, не будет изменяться при выполнении программы, для программного счетчика не существует явления OutOfMemory.
2.Стек Java
Стек Java также называют стеком виртуальной машины (Java Virtual Machine Stack), который мы часто называем стеком, который похож на стек в сегменте данных языка C. По сути, стек Java — это модель памяти для выполнения методов Java. Почему ты это сказал? Давайте объясним, почему.
Стек Java хранит кадры стека один за другим, каждый кадр стека соответствует вызываемому методу, а кадр стека включает в себя таблицу локальных переменных (Local Variables), стек операндов (Operand Stack), указывающий на класс, к которому относится текущий метод. Ссылка на пул констант времени выполнения (Reference to runtime Constant pool), адрес возврата метода (Return Address) и некоторая дополнительная информация. Когда поток выполняет метод, он создает соответствующий кадр стека и помещает созданный кадр стека в стек. Когда метод завершает выполнение, кадр стека извлекается из стека. Следовательно, видно, что кадр стека, соответствующий методу, выполняемому в данный момент потоком, должен находиться наверху стека Java. К этому моменту каждый должен понимать, почему при использовании рекурсивных методов легко происходит переполнение стековой памяти и почему программистам не нужно управлять пространством в области стека (конечно, в Java программистам в принципе не приходится иметь дело с выделение памяти и освобождение вещей, потому что в Java есть свой механизм сборки мусора), выделение и освобождение этой части пространства автоматически реализуются системой. Как и во всех языках программирования, пространство стека непрозрачно для программиста. На следующем рисунке представлена модель стека Java:
таблица локальных переменных, как следует из названия, вы должны понять его функцию, не объясняя ее. Он используется для хранения локальных переменных в методе (включая нестатические переменные, объявленные в параметрах метода и функции). Для переменных базового типа данных хранится непосредственно ее значение, а для переменных ссылочного типа хранится ссылка на объект. Размер таблицы локальных переменных определяется компилятором, поэтому размер таблицы локальных переменных не меняется во время выполнения программы.
стек операндов, Друзья, изучавшие стеки в структурах данных, должны быть знакомы с проблемой вычисления выражений.Одним из наиболее типичных применений стеков является вычисление выражений. Подумайте о процессе выполнения метода потоком, который на самом деле представляет собой процесс непрерывного выполнения операторов и, в конечном счете, процесс вычислений. Поэтому можно сказать, что все вычисления в программе производятся с помощью стека операндов.
ссылка на пул констант времени выполнения, потому что константы в классе могут понадобиться во время выполнения метода, поэтому должна быть ссылка на константы времени выполнения.
адрес возврата метода, когда метод выполняется, он должен вернуться в то место, где он был вызван до этого, поэтому адрес возврата метода должен быть сохранен во фрейме стека.
Поскольку каждый поток может выполнять разные методы, каждый поток будет иметь свой собственный стек Java, не мешая друг другу.
3.собственный стек методов
Функция и принцип стека нативных методов очень похожи на стек Java. Единственное отличие состоит в том, что стек Java предназначен для выполнения методов Java, а стек собственных методов — для выполнения собственных методов. В спецификации JVM нет конкретного метода реализации и структуры данных для локальной разработки, и виртуальная машина может свободно это реализовать. В виртуальной машине HotSopt стек собственных методов и стек Java напрямую объединены в один.
4.куча
В языке C куча — это единственная область памяти, которой может управлять программист. Программисты могут запрашивать и освобождать место в куче с помощью функций malloc и free. Так как же это в Java?
Куча в Java используется для хранения самого объекта и массива (разумеется, ссылка на массив хранится в стеке Java). Он просто отличается от языка C. В Java программистам в основном не нужно заботиться о проблеме освобождения места, и механизм сборки мусора Java автоматически справится с этим. Следовательно, эта часть пространства также является основной областью, управляемой сборщиком мусора Java. Кроме того, куча разделяется всеми потоками, в JVM есть только одна куча.
5.область метода
Область метода также является очень важной областью в JVM, как и куча, это область, разделяемая потоками. В области метода хранится информация о каждом классе (включая имя класса, информацию о методе, информацию о поле), статические переменные, константы и код, скомпилированный компилятором.
В файле класса, помимо информации описания полей, методов и интерфейсов класса, также имеется постоянный пул, который используется для хранения литералов и символьных ссылок, сгенерированных во время компиляции.
Очень важной частью в области методов является пул констант времени выполнения, который представляет собой представление пула констант каждого класса или интерфейса во время выполнения.После того, как класс и интерфейс загружены в JVM, создается соответствующий пул констант времени выполнения. Конечно, только содержимое пула констант файла класса может войти в пул констант времени выполнения, и новые константы также могут быть помещены в пул констант времени выполнения во время выполнения, например, внутренний метод String.
В спецификации JVM нет обязательного требования к областям методов для реализации сборки мусора. Многие люди привыкли называть область методов «постоянной генерацией», потому что виртуальная машина HotSpot реализует область методов в постоянной генерации, так что сборщик мусора JVM может управлять этой частью области, такой как область кучи, поэтому нет необходимости для этой части Спроектируйте механизм сборки мусора. Однако, начиная с JDK7, виртуальная машина Hotspot удалила постоянный пул времени выполнения из постоянного поколения.
Структура памяти объектной модели Java
Java — объектно-ориентированный язык, и хранение объектов Java в JVM также имеет определенную структуру. Эта модель хранения для самих объектов Java называется объектной моделью Java.
В виртуальной машине HotSpot спроектирована Модель ООП-класса. ООП (обычный указатель объекта) относится к обычному указателю объекта, а класс используется для описания конкретного типа экземпляра объекта.
Для каждого класса Java при загрузке JVM JVM создаетinstanceKlass
, хранящийся в области методов и используемый для представления класса Java на уровне JVM. Когда мы используем new для создания объекта в коде Java, JVM создастinstanceOopDesc
Объекты, расположение объектов, хранящихся в памяти, можно разделить на три области: заголовок объекта (Header), данные экземпляра (Instance Data) и заполнение выравнивания (Padding).
- Заголовок объекта: слово-метка (32-битная виртуальная машина 4B, 64-битная виртуальная машина 8B) + указатель типа (32-битная виртуальная машина 4B, 64-битная виртуальная машина 8B) + [длина массива (эта часть информации только требуется для объектов массива)]
- Данные экземпляра: он хранит действительные действительные данные, такие как содержимое различных полей.Стратегия распределения каждого поля: длинные/двойные, целые, короткие/символы, байты/логические значения, oops (обычные указатели на объекты) и поля одного и того же ширина всегда распределяется вместе для легкого доступа к данным позже. Переменные, определенные родительским классом, появляются перед переменными, определенными дочерним классом.
- Заполнение выравнивания: для 64-разрядных виртуальных машин размер объекта должен быть целым числом, кратным 8 Б. Если этого недостаточно, требуется заполнение заполнителя.
Сборщик мусора памяти JVM
Чтобы понять существующих коллекторов, нам нужно сначала понять некоторую терминологию. Самая простая сборка мусора включает в себя идентификацию памяти, которая больше не используется, и ее повторное использование. Современные коллекционеры выполняют этот процесс в несколько этапов, которые мы часто описываем следующим образом:
- Параллельный — во время работы JVM существуют как потоки приложения, так и потоки сборщика мусора. Параллельные этапы выполняются несколькими потоками gc, т.е. работа gc распределяется между ними. Не зависит от того, должен ли поток GC приостановить поток приложения.
- Последовательный — последовательный этап выполняется только в одном потоке gc. Как и прежде, он также не говорит, должен ли поток GC приостановить поток приложения.
- STW — фаза STW, поток приложения приостанавливается, чтобы gc мог выполнить свою работу. Когда приложение приостанавливается из-за GC, это обычно происходит из-за фазы Stop The World.
- Параллелизм. Если этап является параллельным, то поток GC может выполняться одновременно с потоком приложения. Параллельные этапы сложны, поскольку их необходимо обработать до завершения этапа, что может сделать работу недействительной.) поток приложения.
- Инкрементный. Если этап является инкрементным, то он может работать некоторое время, а затем завершаться досрочно из-за какого-либо условия, например, необходимости выполнить этап gc с более высоким приоритетом, при этом продолжая выполнять продуктивную работу. Дополнительные этапы резко контрастируют с этапами, которые требуют полного завершения.
Серийный коллекционер
Последовательный сборщик — это самый простой сборщик, который является однопоточным сборщиком, и он по-прежнему является сборщиком нового поколения JVM по умолчанию в клиентском режиме. У него есть преимущества перед другими сборщиками: он прост и эффективен (по сравнению с однопотоковыми сборщиками), а у сборщика Serial нет накладных расходов на взаимодействие потоков, поэтому естественно сконцентрироваться только на сборке мусора для достижения максимальной эффективности. В сценарии пользовательского рабочего стола память, выделенная для JVM, не слишком велика, а время паузы может составлять от десятков до более 100 миллисекунд, пока сбор не частый, это вполне приемлемо.
Коллекционер ParNew
ParNew — это многопоточная версия Serial, которая в принципе согласуется с алгоритмом повторного использования и размещением объектов. Сборщик ParNew — это сборщик мусора нового поколения по умолчанию, работающий в режиме сервера, главным образом потому, что в дополнение к сборщику Serial в настоящее время только сборщик ParNew может работать со сборщиком CMS.
Параллельный сборщик мусора
Сборщик Parallel Scavenge — это сборщик мусора нового поколения, использующий алгоритм репликации, а также являющийся параллельным многопоточным сборщиком.
Сборщик Parallel Scavenge больше заботится о контролируемой пропускной способности, которая равна времени выполнения пользовательского кода / (время выполнения пользовательского кода + время сборки мусора). Интуитивно понятно, что чем меньше максимальное время приостановки сборки мусора, тем выше пропускная способность, но сокращение времени приостановки сборки мусора происходит за счет пропускной способности и пространства для молодого поколения. Например, если раньше сбор был раз в 10 секунд, а каждая пауза — 100 миллисекунд, то теперь он собирается раз в 5 секунд, а каждая пауза — 70 миллисекунд. Одновременно с уменьшением времени паузы снижается и пропускная способность.
Чем короче время паузы, тем больше подходит программа, которая должна взаимодействовать с пользователем; а высокая пропускная способность позволяет наиболее эффективно использовать время ЦП и выполнять вычислительную задачу как можно быстрее, что в основном подходит для фоновых операций. .
Серийный Старый коллекционер
Сборщик Serial Old — это старая версия сборщика Serial, а также однопоточный сборщик, который использует «алгоритм маркировки-разборки» для повторного использования. Он работает так же, как серийный коллектор.
Параллельный Старый коллектор
Сборщик Parallel Old — это версия сборщика Parallel Scavenge более раннего поколения, которая использует многопоточность и алгоритм пометки и уплотнения для сборки мусора. Обычно он используется в сочетании со сборщиком Parallel Scavenge. Особенностью этой комбинации является сборщик "сначала пропускная способность". Эту комбинацию можно использовать в ситуациях, когда важны пропускная способность и ресурсы ЦП.
Сборщик CMS
Коллектор CMS (Concurrent Mark Sweep) — это сборщик с целью получения кратчайшего времени паузы.Коллектор CMS принимает алгоритм маркировки-развертки и работает в старом возрасте. В основном он включает следующие этапы:
- начальная отметка
- одновременная маркировка
- перемаркировать
- Параллельная очистка
Где первоначальная пометка и повторная пометка по-прежнему требуют «Остановить мир». Начальная метка помечает только те объекты, которые могут быть непосредственно связаны с корнем GC, параллельная метка предназначена для выполнения процесса трассировки корня GC, а повторная метка — для исправления записи метки той части объекта, метка которой изменена. из-за непрерывного выполнения пользовательской программы во время одновременной маркировки.
Поскольку одновременная маркировка и одновременная очистка всего процесса занимают больше всего времени, поток сбора и пользовательский поток работают вместе, поэтому в целом процесс повторного использования сборщика CMS выполняется одновременно с пользовательским потоком. Хотя CMS обладает преимуществами параллельной сборки, низкими паузами и уже в значительной степени является хорошим сборщиком мусора, у нее все же есть три существенных недостатка:
- Сборщик CMS чувствителен к ресурсам ЦП. В параллельной фазе, хотя это и не приведет к остановке пользовательского потока, это приведет к замедлению работы приложения, занимая часть потока (ресурс ЦП).
- Сборщик CMS не может обрабатывать плавающий мусор. Так называемый "плавающий мусор" означает, что в параллельной фазе маркировки, так как пользовательская программа работает, естественно будет генерироваться новый мусор.После того, как эта часть мусора будет маркирована, CMS не может обрабатывать их централизованно в текущий момент времени, поэтому он должен быть обработан в следующем GC.Эта часть необработанного мусора называется «плавающий мусор». Это также связано с тем, что программа все еще должна работать на этапе сборки мусора, то есть необходимо зарезервировать достаточно места в памяти для использования пользователями, поэтому сборщик CMS не может ждать, пока старая эра почти не будет заполнена, прежде чем собирать, как другие сборщики, и должен зарезервировать часть пространства, чтобы обеспечить работу Программы во время параллельного сбора. Если пространство памяти, зарезервированное CMS, не может удовлетворить требованиям программы, это JVM запустит план подготовки: временно запустит сборщик Serial Old для сбора старого поколения, так что время паузы будет очень долгим.
- Поскольку CMS использует алгоритм маркировки и очистки, после сбора происходит значительная фрагментация памяти. Когда слишком много фрагментации памяти, это вызовет трудности с выделением больших объектов, то есть с выполнением полного GC.
коллектор G1
Коллектор G1 — это большое улучшение по сравнению с CMS:
· Коллектор G1 реализован с использованием алгоритма сортировки по отметке.
· Паузой можно очень точно управлять.
Коллектор G1 может обеспечить высвобождение памяти с малой паузой без ущерба для пропускной способности. Это связано с тем, что он пытается избежать высвобождения всей области. Коллектор G1 делит кучу Java (включая новое поколение и старое поколение) на несколько областей (регионов), и вести список приоритетов в фоновом режиме, каждый раз по разрешенному времени отдавать приоритет региону с наибольшим количеством мусора.
коллектор ZGC
Недавно добавленный сборщик мусора ZGC в Java 11 утверждает, что может достигать пауз GC менее 10 мс.ZGC добавляет две новые технологии в сборщики мусора Hotspot: цветные указатели и барьеры чтения. Следующие цитаты из зарубежных статей:
Указатель затенения
Затенение указателей — это метод хранения информации в указателях (или ссылках в терминологии Java). Поскольку на 64-битных платформах (ZGC поддерживает только 64-битные платформы) указатели могут обрабатывать больше памяти, поэтому некоторые биты могут использоваться для хранения состояния. ZGC ограничит поддержку максимальным размером кучи 4 ТБ (42 бита), поэтому будет доступно 22 бита, в настоящее время он использует 4 бита:
finalizable
,remap
,mark0
иmark1
. Мы объясним их назначение позже.Одна проблема с указателями шейдеров заключается в том, что они требуют дополнительной работы (из-за необходимости маскировать биты информации), когда вам нужно отменить шейдер. Такие платформы, как SPARC, имеют встроенную аппаратную поддержку маскирования указателей, так что это не проблема, в то время как для платформ x86 команда ZGC использует хитрый трюк с несколькими отображениями.
Мультикарта
Чтобы понять, как работает multimap, нам нужно кратко объяснить разницу между виртуальной памятью и физической памятью. Физическая память — это фактическая память, доступная системе, обычно емкость установленных микросхем DRAM. Виртуальная память является абстрактной, а это означает, что приложения имеют собственное представление (обычно изолированной) физической памяти. Операционная система отвечает за поддержание сопоставления между диапазонами виртуальной и физической памяти, и она делает это с помощью таблиц страниц, блока управления памятью процессора (MMU) и буфера преобразования (TLB), который преобразует адрес.
Множественное сопоставление включает сопоставление различных диапазонов виртуальной памяти с одной и той же физической памятью. Так как в конструкции только один
remap
,mark0
иmark1
Может быть 1 в любой момент времени, поэтому для этого можно использовать три сопоставления. В исходном коде ZGC есть красивая диаграмма, иллюстрирующая это.прочитать барьер
Барьер чтения — это фрагмент кода, который запускается всякий раз, когда поток приложения загружает ссылку из кучи (т. е. обращается к не примитивному полю объекта):
void printName( Person person ) { String name = person.name; // 这里触发读屏障 // 因为需要从heap读取引用 // System.out.println(name); // 这里没有直接触发读屏障 }
В приведенном выше коде имя строки =person.nameПолучил доступ к ссылке на человека в куче, затем загрузил ссылку в локальную переменную имени. В этот момент срабатывает барьер чтения. Строка Systemt.out не запускает барьер чтения напрямую, поскольку из кучи не загружаются ссылки (имя является локальной переменной, поэтому ссылки из кучи не загружаются). Но система и снаружи или внутри println могут вызвать другие барьеры чтения.
Это отличается от барьеров записи, используемых другими сборщиками мусора, такими как G1. Работа барьера чтения заключается в проверке состояния ссылки и выполнении некоторой работы перед возвратом ссылки (или даже другой ссылки) в приложение. В ZGC он делает это, проверяя загруженные ссылки, чтобы увидеть, установлены ли определенные биты. Если тест пройден, никакая другая работа не выполняется, а если он не пройден, выполняются некоторые задачи, относящиеся к этапу, прежде чем ссылка будет возвращена приложению.
отметка
Теперь, когда мы понимаем, что представляют собой эти две новые технологии, давайте взглянем на цикл ZG GC.
Первая часть цикла GC — маркировка. Маркировка включает в себя поиск и маркировку всех объектов кучи, к которым может получить доступ работающее приложение, другими словами, поиск объектов, которые не являются мусором.
Маркировка ZGC делится на три этапа. Первый этап — STW, где корни GC помечаются как живые объекты. Корни GC аналогичны локальным переменным, через которые можно получить доступ к другим объектам в куче. Объект считается мусором, если к нему нельзя получить доступ, обходя граф объектов, начиная с корней, поэтому приложение также не может получить к нему доступ. Коллекция объектов, доступ к которым осуществляется из корней, называется живой коллекцией. Шаг маркировки корней GC очень короткий, потому что общее количество корней обычно невелико.
После завершения этой фазы приложение возобновляет выполнение, и ZGC начинает следующую фазу, которая одновременно обходит граф объектов и отмечает все доступные объекты. На этом этапе игла барьера чтения проверяет все загруженные ссылки с маской, которая определяет, помечены они или нет, и если нет, то добавляет в очередь на пометку.
После завершения обхода наступает финальная, недолговечная фаза Stop The World, которая обрабатывает некоторые пограничные случаи (которые мы пока игнорируем), а фаза маркировки завершается после завершения этой фазы.
перезагрузить
Следующая важная часть цикла GC — переезды. Перемещение включает в себя перемещение живых объектов, чтобы освободить часть памяти кучи. Зачем перемещать объекты, а не заполнять промежутки? Некоторые сборщики мусора действительно делают это, но это приводит к печальным последствиям: выделение памяти становится более затратным, потому что, когда необходимо выделить память, распределитель памяти должен найти свободное место, где можно разместить объекты. Напротив, если можно освободить большой кусок памяти, выделение памяти так же просто, как увеличение указателя на объем памяти, необходимый для нового объекта.
ZGC делит кучу на множество страниц, и в начале этой фазы одновременно выбирает набор страниц, которым нужно переместить живые объекты. После выбора набора перемещений происходит пауза Stop The World, когда ZGC перемещает корневые объекты в наборе и сопоставляет их ссылки с новым местоположением. Как и в предыдущем шаге «Остановить мир», время паузы здесь зависит только от количества корней и отношения размера набора перемещений к общему активному набору объекта, который обычно довольно мал. Таким образом, в отличие от многих сборщиков, время паузы увеличивается с размером кучи.
После перемещения корня следующим этапом является параллельное перемещение. На этом этапе поток GC проходит через набор перемещений и перемещает все объекты на страницах, которые он содержит. Если поток приложения пытается загрузить объект до того, как GC переместит его, поток приложения также может переместить объект, который может преодолеть барьер чтения (срабатывает, когда ссылка загружается из кучи).
Это гарантирует, что все ссылки, которые видит приложение, будут обновлены, и приложение не сможет работать с перемещенным объектом одновременно.
Поток GC в конечном итоге переместит все объекты в наборе перемещений, однако ссылки на старые местоположения этих объектов все еще могут быть. Сборщик мусора может пройти по графу объектов и переназначить эти ссылки на новые местоположения, но этот шаг требует больших затрат. Таким образом, этот шаг объединяется со следующей фазой маркировки. При обходе графа объектов во время фазы маркировки следующего цикла GC, если найдена неотображенная ссылка, она повторно отображается, а затем помечается как активная.
Оптимизация памяти JVM
В книге "Углубленное понимание виртуальной машины Java" я рассказал о многих идеях оптимизации jvm. Позвольте мне кратко рассказать об этом.
Джава джиттер памяти
Память кучи имеет определенный размер, и данные, которые могут быть размещены, ограничены.Когда размер кучи Java слишком велик, сборка мусора запустит и остановит объекты, которые больше не используются в куче, чтобы освободить память. Теперь термин переполнение памяти можно использовать для описания процесса присвоения объекту за очень короткое время. В частности, как оптимизировать, пожалуйста, запросите Google ~
jvm огромная страничная память
Что такое подкачка памяти?
ЦП обращается к памяти посредством адресации. Ширина адресации 32-разрядного процессора составляет 0~0xFFFFFFFF, то есть 4G, что означает, что максимальная физическая память, которая может поддерживаться, составляет 4G. Однако на практике программе необходимо использовать память 4G, а доступная физическая память меньше 4G, поэтому программе приходится сокращать использование памяти. Для решения таких задач в современных ЦП введеныMMU
(Memory Management Unit, блок управления памятью).
MMU
Основная идея состоит в том, чтобы использовать виртуальные адреса для замены физических адресов, то есть ЦП использует виртуальные адреса при адресации, а MMU отвечает за сопоставление виртуальных адресов к физическим адресам. Введение MMU решает ограничение физической памяти. Для программы он похож на использование памяти 4G.
подкачка памяти(Paging) — механизм управления памятью, предложенный на основе использования MMU. Он разделяет виртуальные и физические адреса на страницы и фреймы страниц в соответствии с фиксированным размером (4 КБ) и гарантирует, что страницы и фреймы страниц имеют одинаковый размер. Этот механизм с точки зрения структуры данных обеспечивает эффективный доступ к памяти и позволяет ОС поддерживать несмежное выделение памяти. Когда программной памяти недостаточно, редко используемые страницы физической памяти также могут быть перенесены на другие устройства хранения, например, на диски, являющиеся виртуальной памятью.
Вы должны знать, что виртуальные адреса и физические адреса должны быть сопоставлены для правильной работы ЦП. Отображение должно хранить таблицу сопоставления. В современных архитектурах ЦП сопоставления обычно хранятся в месте, называемом таблицей страниц в физической памяти. Таблица страниц хранится в памяти, и ЦП обращается к памяти через шину, что определенно медленнее, чем обращение к регистру напрямую. Для дальнейшей оптимизации производительности современные архитектуры ЦП вводятTLB
(резервный буфер перевода, регистровый буфер таблицы страниц), используемый для кэширования части часто используемого содержимого таблицы страниц.
Зачем поддерживать большую подкачку памяти?
TLB ограничен, в этом нет сомнений. Когда предел хранения TLB превышен, происходит промах TLB, и ОС дает указание ЦП получить доступ к таблице страниц в памяти. При частых промахах TLB производительность программы будет быстро снижаться.
Чтобы позволить TLB хранить больше соотношений сопоставления адресов страниц, наш подход заключается в увеличении размера страницы памяти.
Если сравнить страницу размером 4 МБ со страницей размером 4 КБ, первая может позволить TLB хранить еще 1000 связей сопоставления адресов страниц, и улучшение производительности будет значительным.
Включить огромную страничную память JVM
Когда JVM включена, добавьте параметр -XX:LargePageSizeInBytes=10m. Если JDK более ранней версии, чем обновление 1.55, вам также необходимо добавить -XX:+UseLargePages, чтобы включить поддержку больших страниц памяти.
Улучшить производительность использования памяти JVM с помощью мягких и слабых ссылок
сильный и слабый
- Сильная цитата:
Пока существует ссылка, сборщик мусора никогда не соберет
Object obj = new Object();
// Соответствующий объект можно получить напрямую через obj, например, obj.equels(new Object());
Таким образом, объект obj имеет сильную ссылку на следующий новый объект.Только когда ссылка obj освобождается, объект освобождается, что также является формой кодирования, которую мы часто используем.
- Мягкие ссылки (могут реализовать кэширование):
Необязательные ссылки, перезапуск перед переполнением памяти, могут быть достигнуты с помощью следующего кода
Object obj = new Object();
SoftReference<Object> sf = new SoftReference<Object>(obj);
obj = null;
sf.get();//有时候会返回null
В настоящее время sf является мягкой ссылкой на obj, и объект можно получить с помощью метода sf.get().Конечно, когда объект помечен как объект, который необходимо переработать, возвращается null; пользователь мягкой ссылки реализует функцию, подобную кешу, когда памяти достаточно, значение получается напрямую через мягкую ссылку, и нет необходимости запрашивать данные из занятого реального источника, что повышает скорость; когда память недостаточно, эта часть кэшированных данных автоматически удаляется, и данные запрашиваются из реального источника.
- Слабые ссылки (используются для предотвращения утечек памяти в функциях обратного вызова):
Переработка во время второй сборки мусора может быть достигнута с помощью следующего кода
Object obj = new Object();
WeakReference<Object> wf = new WeakReference<Object>(obj);
obj = null;
wf.get();//有时候会返回null
wf.isEnQueued();//返回是否被垃圾回收器标记为即将回收的垃圾
Слабые ссылки собираются во время второй сборки мусора. Соответствующие данные можно получить через слабые ссылки за короткий промежуток времени. При выполнении второй сборки мусора будет возвращено значение null. Слабая ссылка в основном используется для контроля того, помечен ли объект как мусор для сбора сборщиком мусора.Метод слабой ссылки isEnQueued может возвращать, помечен ли объект сборщиком мусора.
- Фиктивная ссылка:
Переработка во время сборки мусора, значение объекта не может быть получено по ссылке, что может быть достигнуто с помощью следующего кода
Object obj = new Object();
PhantomReference<Object> pf = new PhantomReference<Object>(obj);
obj=null;
pf.get();//永远返回null
pf.isEnQueued();//返回是否从内存中已经删除
Виртуальная ссылка перерабатывается каждый раз при сборке мусора.Данные, полученные методом get виртуальной ссылки, всегда равны нулю, поэтому ее также называют фантомной ссылкой. Фантомные ссылки в основном используются для определения того, был ли объект удален из памяти.
оптимизация
Короче говоря, вы можете использовать программные ссылки для ссылки на огромное количество объектов.
Суммировать
В этой статье всего 1,5 Вт слов.Я рассказал о модели памяти Java из системы физической памяти компьютера и представил соответствующие точки знаний о памяти JVM через модель памяти Java. Если вы считаете, что это хорошо написано, пожалуйста, поставьте палец вверх. Эта статья сначала будет опубликована в моем личном блоге, а затем будет опубликована на таких платформах, как Nuggets. Наконец, большое спасибо за чтение ~
использованная литература
Различные гиперссылки в тексте
"Глубокое понимание виртуальной машины Java"
Искусство параллельного программирования на Java
«Расшифровка архитектуры от распределенной к микросервисам»
Введение в архитектуру SMP, NUMA, MPP
Принцип ZGC (пожалуйста, используйте магию правильной позы, чтобы смотреть онлайн)
утверждение
[Заявление об авторских правах] Этот фильм является оригинальным контентом, используя условия лицензии MIT, пожалуйста, соблюдайте соответствующие обязательства, то есть лицензиат обязан включать заявление об авторских правах во все копии. Спасибо за сотрудничество~
Хотите разблокировать больше новых поз? Пожалуйста, посетите мой личный блог https://blog.tengshe789.tech/ (😘 адрес сообщества github https://github.com/tengshe789/, добро пожаловать в fo