Java jvm option list

Java jvm option list

  • Haskell vs. PureScript: The difference is complexity Haskell and PureScript each provide their own unique development advantages, so how should developers choose between these two .
  • A quick intro to the MACH architecture strategy While not particularly prescriptive, alignment with a MACH architecture strategy can help software teams ensure application .
  • How to maintain polyglot persistence for microservices Managing microservice data may be difficult without polyglot persistence in place. Examine how the strategy works, its challenges.
  • GitHub Copilot Chat aims to replace Googling for devs GitHub’s public beta of Copilot Chat rolls out GPT-4 integration that embeds a chat assistant into Visual Studio, but concerns .
  • The basics of implementing an API testing framework With an increasing need for API testing, having an efficient test strategy is a big concern for testers. How can teams evaluate .
  • The potential of ChatGPT for software testing ChatGPT can help software testers write tests and plan coverage. How can teams anticipate both AI’s future testing capabilities .
  • 5 Google Cloud cost optimization best practices Cost is always a top priority for enterprises. For those considering Google Cloud, or current users, discover these optimization .
  • How to create and manage Amazon EBS snapshots via AWS CLI EBS snapshots are an essential part of any data backup and recovery strategy in EC2-based deployments. Become familiar with how .
  • Prices for cloud infrastructure soar 30% Tough macroeconomic conditions as well as high average selling prices for cloud computing and storage servers have forced .
  • API keys: Weaknesses and security best practices API keys are not a replacement for API security. They only offer a first step in authentication — and they require additional .
  • Risk & Repeat: Are data extortion attacks ransomware? Ransomware gangs are focusing more on data theft and extortion while skipping the encryption of networks. But should these .
  • Cyber insurers adapting to data-centric ransomware threats Cyber insurance carriers and infosec vendors weigh in on how the shift in ransomware tactics is affecting policies and coverage, .
  • AWS Control Tower aims to simplify multi-account management Many organizations struggle to manage their vast collection of AWS accounts, but Control Tower can help. The service automates .
  • Break down the Amazon EKS pricing model There are several important variables within the Amazon EKS pricing model. Dig into the numbers to ensure you deploy the service .
  • Compare EKS vs. self-managed Kubernetes on AWS AWS users face a choice when deploying Kubernetes: run it themselves on EC2 or let Amazon do the heavy lifting with EKS. See .
Читайте также:  Php define application path

Источник

Опции JVM. Как это работает

С каждым днем слово java все больше и больше воспринимается уже не как язык, а как платформа благодаря небезызвестному invokeDynamic. Именно поэтому сегодня я бы хотел поговорить про виртуальную java машину, а именно — об так называемых Performance опциях в Oracle HotSpot JVM версии 1.6 и выше (server). Потому что сегодня почти не встретить людей, которые знают что-то больше чем -Xmx, -Xms и -Xss. В свое время, когда я начал углубляться в тему, то обнаружил огромное количество интересной информации, которой и хочу поделится. Отправной точкой, понятное дело, послужила официальная документация от Oracle. А дальше — гугл, эксперименты и общение:

-XX:+DoEscapeAnalysis

Начну, пожалуй, с самой интересной опции — DoEscapeAnalysis. Как многие из Вас знают, примитивы и ссылки на объекты создаются не в куче, а выделяются на стеке потока (256КБ по умолчанию для Hotspot). Вполне очевидно, что язык java не позволяет создавать объекты на стеке на прямую. Но это вполне себе может проделывать Ваша JVM 1.6 начиная с 14 апдейта.

Про то, как работает сам алгоритм можно прочитать тут (PDF). Если коротко, то:

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

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

  • GlobalEscape — объект доступен из других потоков и из других методов, например статическое поле.
  • ArgEscape — объект был передан как аргумент или на него есть ссылка из объекта аргумента, но сам он не выходит из области видимости потока в котором был создан.
  • NoEscape — объект не покидает область видимости метода и его создание может быть вынесено на стек.
Читайте также:  What is after java

После этапа анализа, уже сама JVM проводит возможную оптимизацию: в случае если объект NoEscape, то он может быть создан на стеке; если объект NoEscape или ArgEscape, то операции синхронизации над ним могут быть удалены.

Следует уточнить, что на стеке создается не сам объект а его поля. Так как JVM заменяет цельный объект на совокупность его полей (спасибо Walrus за уточнение).

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

скорость выполнения может увеличится в 8-15 раз. Хотя, на казалось бы, очевидных случаях из практики о которых недавно писалось (тут и тут) EscapeAnalys не работает. Подозреваю, что это связано с размером стека.

Кстати, EscapeAnalysis как раз частично ответственен за известный спор про StringBuilder и StringBuffer. То есть, если Вы вдруг в методе использовали StringBuffer вместо StringBuilder, то EscapeAnalysis (в случае срабатывания) устранит блокировки для StringBuffer’а, после чего StringBuffer вполне превращается в StringBuilder.

-XX:+AggressiveOpts

Опция AggressiveOpts является супер опцией. Не в том плане, что она резко увеличивает производительность Вашего приложения, а в том смысле, что она всего лишь изменяет значения других опций (на самом деле, это не совсем так — в исходном коде JDK довольно не мало мест, где AggressiveOpts изменяет поведение JVM, помимо упомянутых опций, один из примеров тут). Проверять измененные флаги будем с помощью двух команд:

java -server -XX:-AggressiveOpts -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal > no_aggr java -server -XX:+AggressiveOpts -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal > aggr 

После выполнения разница в результатах выполнения команд выглядела так:

-AggressiveOpts +AggressiveOpts
AutoBoxCacheMax 128 20000
BiasedLockingStartupDelay 4000 500
EliminateAutoBox false true
OptimizeFill false true
OptimizeStringConcat false true

Иными словами, все что делает эта опция — изменяет 5 данных параметров виртуальной машины. Причём, для версий 1.6 update 35 и 1.7 update 7 никаких отличий замечено не было. Данная опция по умолчанию отключена и в клиентском моде ничего не изменяет.
Расcмотрим, что же java подразумевает под агрессивной оптимизацией:

-XX:AutoBoxCacheMax=size

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

-XX:BiasedLockingStartupDelay=delay

Как известно, synchronized блок в java может быть представлен одним из 3-х видов блокировок:

Так как большинство объектов (синхронизированных) блокируются максимум 1 одним потоком, то такие объекты могут быть привязаны (biased) к этому потоку и операции синхронизации над этим объектом внутри потока сильно удешевляются. Если к biased объекту пытается получить доступ другой поток, то происходит переключение блокировки для этого объекта на thin блокировку.

Само переключение относительно дорого, поэтому на старте JVM существует задержка, которая по умолчанию создает все блокировки как thin и если никакой конкуренции не обнаружено и код используется одним и тем же потоком, то такие блокировки, после истечения задержки, становятся biased. То есть, JVM пытается на старте определить сценарии использования блокировок и соответственно использует меньше переключений между ними. Соответственно, выставляя BiasedLockingStartupDelay в ноль, мы рассчитаем на то, что основные куски кода синхронизации будут использоваться лишь одни и тем же потоком.

-XX:+OptimizeStringConcat

Тоже довольно интересная опция. Распознает паттерн на подобии

StringBuilder().append(. ).toString() //или рекурсивного вида StringBuilder().append(new StringBuiler().append(. ).toString()).toString() 

и вместо постоянного выделения памяти под новую операцию конкатенации, идет попытка вычислить общее количество символов каждого объекта конкатенации для выделения памяти только 1 раз.
Иными словами, если мы вызовем 20 раз операцию append() для строки длинной 20 символов. То создание массива char произойдет один раз и длиной 400 символов.

XX:+OptimizeFill

Циклы заполнения/копирования массивов заменяются на прямые машинные инструкции для ускорения работы.
Например, следующий блок (взято из Arrays.fill()):

будет полностью замен на соответствующие процессорные инструкции на подобии сишных memset, memcpy только более низкоуровневых.

XX:+EliminateAutoBox

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

-XX:+UseCompressedStrings

Довольно спорная опция по моему убеждению… Если в далеких 90-х разработчики java не пожалели 2 байта на символ, то сегодня такая оптимизация смотрится довольно нелепо. Если кто не догадался, то опция заменяет в строках символьные массивы на байтовые, где это возможно (ASCII). По сути:

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

-XX:+UseStringCache

Довольно загадочная опция, судя по названию она должна каким-то образом кешировать строки. Как? Не понятно. Информации нету. Да и по коду похоже она ничего не выполняет. Буду рад, если кто-то сможет прояснить.

-XX:+UseCompressedOops

Для начала несколько фактов:

  • Размер указателя на объект в 32-х разрядной JVM составляет 32 бита. В 64-х разрядной — 64 бита. Следовательно, в первом случае Вы можете использовать адресное пространство размером 2^32 байт (4 ГБ), а во втором случае 2^64 байт.
  • Размер объектов в java кратен 8 байтам не зависимо от разрядности виртуальной машины (это не для всех виртуальных машин правда, но речь о Hotspot). То есть, при использовании 32-х разрядных указателей последние 3 бита будут всегда нулями, фактически, виртуальная машина реально использует лишь 29 бит.

Данная опция позволяет уменьшить размер указателя для 64-х разрядных JVM до 32-х бит, но в этом случае размер кучи ограничен 4 ГБ, поэтому, в дополнение к сокращенному указателю, используется свойство о кратности 8 байтам. В результате получаем возможность использовать адресное пространство размером 2^35 байт (32 ГБ) имея указатели в 32 бита.
Фактически, внутри виртуальной машины, мы имеем указатели на объекты, а не конкретные байты в памяти. Понятное дело, что из-за подобных допущений (о кратности) появляются дополнительные расходы на преобразование указателей. Но по сути это всего лишь одна операция сдвига и суммирования.

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

То есть, из недостатков имеем лишь:

  • Максимальный размер кучи ограничен 32 ГБ (64ГБ для JRockit при кратности объектов 16 байтам);
  • Появляются доп. расходы на преобразование JVM ссылок в нативные и обратно.

Так как для большинства приложений опция несет одни плюсы, то начиная с JDK 6 update 23 она включена по умолчанию, так же как и в JDK 7. Детальней тут и тут.

-XX:+EliminateLocks

Опция, которая устраняет лишние блокировки путем их объединения. Например следующие блоки:

synchronized (object) < //doSomething1 >synchronized (object) < //doSomething2 >
synchronized (object) < //doSomething3 >//doSomething4 synchronized (object) < //doSomething5 >

будут преобразованы соответственно в

Таким образом сокращается количество попыток захвата монитора.

Заключение

За бортом осталось довольно много интересных опций, так как поместить все ~700 флагов в одну статью довольно трудно. Я специально не затрагивал опции по тюнингу сборщика, так это довольно обширная и сложная тема и она заслуживает нескольких постов. Надеюсь статья была вам полезной.

Источник

Оцените статью