Это продолжение предыдущего поста под названием (Часть 1 из 3): краткий обзор статей и видео по настройке производительности, JVM, GC in Java, Mechanical Sympathy и др .
Без лишних слов, давайте начнем с нашего следующего набора блогов и видео, чоп… чоп…! На этот раз его сообщения в блоге Мартина Томпсона и разговоры. Первая статья Мартина о сборке мусора на Java в основном содержит информацию о процессе GC и лежащих в его основе компонентах, включая освещение ряда интересных флагов GC ( -XX:… ). В своем следующем выступлении он исполнил свой миф о разрушении шаабанга о механической симпатии, во что люди верят правильно и в заблуждения. В разговоре о тестировании производительности Мартин идет дальше и объединяет Java, ОС и аппаратное обеспечение, чтобы показать, как понимание всех этих аспектов может помочь в написании лучших программ.
Сборка мусора на Java, дистиллированная Мартином Томпсоном
Слишком много флагов, чтобы позволить настроить GC для достижения пропускной способности и задержки, требуемой для вашего приложения. Существует множество документов о специфике колокольчиков и свистков вокруг них, но нет ни одной, которая поможет вам пройти через них.
Компромиссы
пропускная способность ( -XX: GCTimeRatio = 99 ), задержка ( -XX: MaxGCPauseMillis = <n> ) и память ( -Xmx <n> ) являются ключевыми переменными, от которых зависят коллекторы. Важно отметить, что Hotspot часто не может достичь вышеуказанных целей. Если приложение с низкой задержкой перестает отвечать на запросы более чем на несколько секунд, это может привести к аварии. Компромиссы разыгрываются как они
- обеспечить больше памяти для алгоритмов GC
- GC может быть уменьшен за счет ограничения живого набора и небольшого размера кучи
- Частота пауз может быть уменьшена путем управления размерами кучи и генерации, а также путем управления скоростью выделения объектов приложения.
- Частота больших пауз может быть уменьшена при одновременном запуске GC
Время жизни объекта
Алгоритмы GC часто оптимизируются с расчетом на то, что большинство объектов живут в течение очень короткого периода времени, а относительно немногие живут очень долго. Эксперименты показали, что сборочные сборщики мусора поддерживают гораздо лучшую пропускную способность, чем не поколенные, поэтому используются в серверных JVM.
События Stop-The-World
Для того, чтобы произошел GC, необходимо, чтобы все потоки работающего приложения были приостановлены — сборщики мусора делают это, сигнализируя потокам об остановке, когда они достигают безопасной точки. Время до безопасной точки является важным фактором в приложениях с низкой задержкой, и его можно найти с помощью флага ‑XX: + PrintGCApplicationStoppedTime в дополнение к другим флагам GC.
Когда происходят события STW, система подвергнется значительному давлению планирования, поскольку потоки возобновляются после освобождения из безопасных точек, следовательно, меньшее количество STW делает приложение более эффективным.
Организация кучи в Hotspot
Куча Java разделена на различные области, объект создан в Eden и перемещен в пространства оставшихся в живых, и в конечном итоге в постоянное владение. PermGen использовался для хранения объектов времени выполнения, таких как классы и статические строки. Коллекционеры используют виртуальные пространства для достижения целей пропускной способности и задержек, а также для настройки размеров регионов для достижения целей.
Распределение объектов
TLAB (Thread Local Allocation Buffer) используется для выделения объектов в Java, что дешевле, чем использование malloc (на большинстве платформ требуется 10 инструкций). Скорость второстепенного сбора прямо пропорциональна скорости размещения объектов. Большие объекты ( -XX: PretenureSizeThreshold = n ), возможно, придется размещать в Old Gen, но если порог установлен ниже размера TLAB, то они не будут созданы в старом поколении — (примечание) не применяется к сборщику G1 .
Незначительные Коллекции
Незначительный сбор происходит, когда Eden заполняется, объекты перемещаются в постоянное пространство из eden, как только они стареют, т.е. пересекают порог ( -XX: MaxTenuringThreshold ). В незначительной коллекции живые достижимые объекты с известными корнями GC копируются в пространство выживших. Hotspot поддерживает ссылки между поколениями, используя карточный стол. Следовательно, размер старого поколения также является фактором стоимости мелких коллекций. Эффективность сбора можно получить, подгоняя размер Eden к числу объектов, которые нужно продвигать. Они склонны к STW и, следовательно, проблематичны в последнее время.
Основные Коллекции
Крупные коллекции собирают старое поколение, чтобы можно было продвигать объекты молодого поколения. Сборщики отслеживают порог заполнения для старого поколения и начинают сбор, когда этот порог пройден. Чтобы избежать провала промоушена, вам нужно настроить отступы, которые старое поколение позволяет размещать в акциях ( -XX: PromotedPadding = <n> ). Изменения размера кучи можно избежать с помощью флагов — Xms и -Xmx . Уплотнение старого поколения вызывает одну из самых больших пауз STW, которую может испытать приложение, и прямо пропорционально количеству живых объектов в старом поколении. Пространство владения можно заполнять медленнее, регулируя размеры оставшегося в живых и порог владения, но это, в свою очередь, может привести к более длительным небольшим временам приостановки сбора в результате увеличения затрат на копирование между оставшимися в живых пространствами.
Серийный коллектор
Это самый простой сборщик с наименьшим размером ( -XX: + UseSerialGC ) и использует один поток как для небольших, так и для основных коллекций.
Параллельный коллектор
Поставляется в двух формах ( -XX: + UseParallelGC ) и ( -XX: + UseParallelOld GC ) и использует несколько потоков для второстепенных коллекций и один поток для основных коллекций — поскольку Java 7u4 использует несколько потоков для обоих типов коллекций. Parallel Old отлично работает на многопроцессорной системе, подходящей для пакетных приложений. Этому сборщику можно помочь, предоставляя больше памяти, больше, но меньше пауз в сборе. Взвесьте ставки между сборщиком Parallel Old и Concurrent в зависимости от того, сколько пауз может выдержать ваше приложение (ожидайте паузы от 1 до 5 секунд на ГБ данных в реальном времени на современном оборудовании, пока сжатый старый поколение).
Concurrent Mark Sweep (CMS) Collector
Сборщик CMS ( -XX: + UseConcMarkSweepGC ) работает в старом поколении, собирая постоянные объекты, которые более недоступны во время основной коллекции. CMS не является компактным сборщиком, вызывающим фрагментацию в Old gen с течением времени. Ошибка продвижения активирует FullGC, когда крупный объект не помещается в Old gen. CMS работает вместе с вашим приложением, занимая процессорное время. CMS может страдать от «одновременных сбоев режима», когда не удается собрать данные с достаточной скоростью, чтобы не отставать от продвижения.
Сборщик мусора первый (G1)
G1 ( -XX: + UseG1GC ) — это новый сборщик, представленный в Java 6 и теперь официально поддерживаемый в Java 7. Это сборщик поколений с частично параллельным алгоритмом сбора, компактирующий Old gen с меньшими инкрементальными паузами STW. Он делит кучу на фиксированные по размеру области переменного назначения. G1 является целевым объектом с задержкой ( –XX: MaxGCPauseMillis = <n> , значение по умолчанию = 200 мс). Сбор на огромных регионах может быть очень дорогостоящим. Он использует «Запомненные наборы» для отслеживания ссылок на объекты из других регионов. Существует много затрат, связанных с ведением бухгалтерского учета и обслуживания «Запоминающиеся наборы». Подобно CMS, G1 может страдать от сбоя при эвакуации (переполнение пространства).
Альтернативные Параллельные Коллекторы
Oracle JRockit Real Time, IBM Websphere Real Time и Azul Zing являются альтернативными параллельными коллекторами. Zing, по словам автора, является единственным сборщиком Java, который соблюдает баланс между сборкой, уплотнением и поддерживает высокую пропускную способность для всех поколений. Zing работает одновременно на всех этапах, в том числе во время незначительных сборов, независимо от размера кучи. Для всех одновременных сборщиков, нацеленных на задержку, вы должны отказаться от пропускной способности и увеличить площадь. Бюджет для размера кучи должен быть не менее чем в 2–3 раза больше действующего набора для эффективной работы.
Мониторинг и настройка сбора мусора
Важные флаги, которые всегда позволяли собирать оптимальные детали GC:
1
2
3
4
5
6
7
|
-verbose:gc -Xloggc:<filename> -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintTenuringDistribution -XX:+PrintGCApplicationConcurrentTime -XX:+PrintGCApplicationStoppedTime |
Используйте приложения, такие как Chewiebug , JVisualVM (с плагином Visual GC), чтобы изучить поведение вашего приложения в результате действий GC. Запускайте репрезентативные нагрузочные тесты, которые можно выполнять неоднократно (по мере приобретения знаний о различных коллекторах), продолжайте экспериментировать с различными конфигурациями, пока не достигнете целевых показателей пропускной способности и задержки. jHiccup помогает отслеживать паузы в JVM. Как нам известно, трудно найти баланс между требованиями к задержке, высоким распределением объектов и скоростью продвижения, а также то, что иногда выбор коммерческого решения для достижения этой цели может быть более разумной идеей.
Вывод: GC сам по себе является большой темой и имеет ряд компонентов, некоторые из которых постоянно заменяются, и важно знать, что означает каждый из них. Флаги GC так же важны, как и компонент, с которым они связаны, и важно знать их и как их использовать. Включение некоторых стандартных флагов GC для записи журналов GC не оказывает существенного влияния на производительность JVM. Использование сторонних бесплатных или коммерческих инструментов поможет, если вы будете следовать методологии авторов.
— Многократно читал статью, так как Мартин освещал множество деталей о GC и коллекционерах, что требует тщательного изучения и хорошего понимания. —
Мартина Томпсона: мифологическое современное оборудование, чтобы получить «Механическое сочувствие» Видео * Слайды
Он классифицирует миф на три категории — возможные , правдоподобные и разрушенные ! Чтобы извлечь максимум пользы из имеющегося у вас оборудования, вам нужно ЗНАТЬ свое оборудование. Делайте компромиссы, меняя ручки, это не так страшно, как вы думаете.
Хороший вопрос: понимают ли обычные разработчики аппаратное обеспечение, на котором они программируют? Или не можете понять, что происходит? Или у нас есть дисциплина и мы прилагаем усилия, чтобы понять платформу, с которой мы работаем?
Миф 1
Процессоры не становятся быстрее — тактовая частота — это еще не все, архитектура Sandy Bridge — самая быстрая порода. 6 портов для поддержки параллельности (6 операций / цикл). Haswell имеет 8 портов! Код, выполняющий операции деления, работает медленнее, чем любые другие арифметические операции. CPU имеет как входной, так и задний циклы. Это становится быстрее, так как мы кормим их быстрее — НАДЕЖНО
Миф 2
Память предоставляет нам произвольный доступ — регистры и буферы ЦП, внутренние кэши (L1, L2, L3) и память — упоминается в порядке, в котором скорость доступа к этим областям увеличивается соответственно. Процессоры делают вещи, чтобы снизить его рабочую температуру, выполняя операции прямого доступа. Записывает меньше хлопот, чем зачитывает — ошибки в буфере обходятся дорого. L1 организован в строки кэша, содержащие код, который будет выполнять процессор — эффективность достигается за счет отсутствия пропусков строк кэша. Средства предварительной выборки помогают уменьшить задержку и помогают во время чтения потоковых и предсказуемых данных. Промахи TLB также могут быть экономически эффективными (4K = размер страницы памяти). Короче говоря, память для чтения не совсем близка к чтению случайно, но ПОСЛЕДОВАТЕЛЬНО из-за того, как работает базовое оборудование. Написание сильно разветвленного кода может привести к замедлению выполнения программы — держать все вместе, что является «связным», является ключом к эффективности. — BUSTED
Примечание: TLAB и TLB — это две разные концепции!
Миф 3
Жесткий диск обеспечивает произвольный доступ — вращающийся диск и рука перемещаются по чтению данных. На внешних дорожках размещено больше секторов, чем на внутренних дорожках (запись битов зоны). Быстрое вращение дисков — это не способ повысить производительность жесткого диска. 4K — это минимум, который вы можете читать или писать. Время поиска на лучшем диске составляет 3-6 мс, диски ноутбука медленнее (15 мс). Задержка вращения занимает некоторое время. Передача данных занимает 100-220 Мбайт / с. Добавление кэша может улучшить запись данных на диск, не так много для чтения данных с дисков. — BUSTED
Миф 4
SSD обеспечивает произвольный доступ — Чтение и запись великолепны, работают очень быстро (4K за раз). Удаление не похоже на фактическое удаление, оно помечено как удаленное и не удаленное на самом деле — так как вы не можете стереть с высоким разрешением, следовательно, весь блок должен быть удален за один раз (следовательно, помечен как удаленный). Все это может привести к фрагментации, и GC и уплотнение не требуется. Чтение происходит плавно, запись затрудняется фрагментацией, сборкой мусора, сжатием и т. Д., А также с учетом усиления записи. Несколько недостатков при использовании SSD, но в целом вполне производительный. — УДОВОЛЬСТВЕННЫЙ
Можем ли мы понять все это и написать лучший код?
Вывод: не принимайте все в пространстве как должное только потому, что он находится на жесткой поверхности, изучайте, осматривайте и исследуйте для себя внутренние устройства, где это возможно, прежде чем считать это возможным или правдоподобным — чтобы написать хороший код и воспользоваться этими преимуществами. функции.
— Отличный разговор и хорошее освещение темы механической симпатии с хорошим настроением, посмотрите видео со статистикой производительности, собранной для каждого из перечисленных выше аппаратных компонентов.
«Тестирование производительности Java-приложений» Мартина Томпсона
Вещи, которые мы используем, как «Как использовать профилировщик?» или «Как использовать отладчик?»
Что такое производительность? Может означать две вещи, такие как пропускная способность или пропускная способность (сколько вы можете пройти) и задержка (как быстро система реагирует).
Время отклика меняется по мере увеличения нагрузки на систему. Прежде чем разрабатывать какую-либо систему, нам нужны требования к производительности, то есть какова пропускная способность системы или как быстро вы хотите, чтобы система реагировала (задержка)? Ваша система экономически масштабируется с вашим бизнесом?
Время разработки дорого, железо дешево! Для чего-либо вам нужен бюджет транзакций (с хорошим разбивкой по различным компонентам и процессам, через которые будет проходить система).
Как мы можем сделать тестирование производительности? Подайте нагрузку на систему и посмотрите, будет ли пропускная способность повышаться или понижаться? И каково время отклика системы при применении нагрузки. Стресс-тестирование отличается от нагрузочного тестирования (см. Нагрузочное тестирование ), стресс-тестирование (см. Стресс-тестирование ) — это точка, в которой вещи ломаются (крах системы), идеальная система будет продолжаться плоской линией. Также важно проводить нагрузочное тестирование не только из одной точки, но из нескольких точек и одновременно. Самое главное, очень важно провести длительное тестирование, которое приводит к появлению множества аномалий на поверхности, например утечек памяти и т. Д.
Хорошая идея — создать набор тестов, состоящий из небольших частей. Нам нужно знать основные строительные блоки системы, которую мы используем, и что мы можем из нее извлечь. Знаем ли мы различные пороговые значения наших систем и сколько их компонентов могут обрабатывать? Очень важно знать алгоритмы, которые мы используем, уметь их измерять и использовать их соответствующим образом — обращайтесь к реальным данным.
Когда мы должны проверить производительность?
«Преждевременная оптимизация — корень всего зла» — Дональд Кнут / Тони Хоар
Что означает оптимизация? Знание и выбор ваших данных и работа с ними для повышения производительности. Новые практики разработки: нам нужно тестировать рано и часто!
С точки зрения производительности очень важна практика «сначала проверить», а затем постепенно проектировать систему, так как изменения могут дорого стоить в будущем.
Красный — Зеленый — Отладка — Профиль — Рефакторинг, новый способ «сначала протестировать» методологию производительности, в отличие от только методологии Красный-Зеленый-Рефакторинг! Более ранний и короткий цикл обратной связи лучше, чем выяснение чего-либо в будущем.
Используйте «как живые» станции сопряжения, Mac — плохой пример для работы, если вы работаете в пространстве Performance — лучше использовать Linux-машину.
Тесты производительности могут не сработать при сборке, а при вашей системе CI — при сбое! Как должен выглядеть микро тест (например, штангенциркуль)? Деление в вашем коде может быть очень дорогим, вместо этого используйте оператор маски !
А как насчет параллельного тестирования? Это просто производительность? Инварианты? Разногласия?
Как насчет тестов производительности системы? Должны ли мы иметь возможность тестировать больших и маленьких клиентов с разными диапазонами. Интересно узнать подробности о системе, над которой вы работаете. Бизнес-проблема является основной и самой важной для решения, а НЕ для обсуждения того, какие рамки использовать для ее создания . Пожалуйста, не используйте сериализацию Java, так как она не предназначена для протокола по проводам! Измеряйте производительность системы с помощью наблюдателя, а не измеряйте ее изнутри системы.
Уроки тестирования производительности — много технических вещей и много культурных вещей. Технические уроки — научитесь измерять, посмотрите гистограммы! Не делайте выборку из системы, мы упускаем из виду, когда дела идут странно, выбросы и т. Д. — гистограммы помогают! Важно знать, что происходит вокруг областей, где система занимает много времени! Захват времени из ОС также очень важен.
Со временем вы получите точность, точность и разрешение, и большинство людей все это смешивают. На машинах с двойными розетками время может не синхронизироваться. Качество информации о времени очень зависит от используемой вами ОС. Время может быть проблемой в виртуализированных системах или между двумя разными машинами. Эта проблема, которая может быть решена, состоит в том, чтобы выполнить двустороннюю операцию между двумя системами (обратите внимание на время начала и окончания часов) и половину из них, чтобы получить более точное время.
Знайте свою систему, ее основные компоненты — получите метрики и изучите их! Используйте инструмент linux, такой как perstat , который даст много информации о производительности и статистике вашего ЦП и ОС — прогнозы веток и ошибки кеша!
RDTSC не является системой исполнения команд-заказов, x86 — системой упорядоченных команд, и операции не происходят неупорядоченным образом.
Теория ограничений! — Всегда начинайте с номера 1, который занимает большую часть времени — узкое место в вашей системе, оставшаяся последовательность проблем может зависеть от номера 1, а не от отдельных проблем!
Попытка создать команду производительности — это анти-паттерн — заставить экспертов помочь донести навыки до остальной части команды и расширить их возможности!
Остерегайтесь YAGNI — о выполнении тестов производительности — запах оправдания!
Фиксация сборки> 3,40 минуты = беспокойство, то же самое для сборки приемочного теста> 15 минут = снижение доверия команды.
Тестовая среда должна соответствовать производственной среде! В наши дни легко получить точно такое же оборудование!
Заключение. Начните с тестирования производительности в первую очередь при написании приложений с низкой задержкой. Знайте свои цели и работайте для этого. Знайте свои базовые системы на всем пути от оборудования до среды разработки. Важны не только технические аспекты, но и культурные аспекты, когда дело доходит до тестирования производительности. Делитесь знаниями и распространяйте их по всей команде, а не изолируйте их одному или двум людям, т.е. так называемым экспертам в команде. Это ответственность каждого, а не нескольких пожилых людей в команде. Узнайте больше о времени между различными аппаратными и операционными системами, а также между системами.
Поскольку просмотр таких видео и статей практически невозможен, некоторые из них были предоставлены по ссылкам ниже для дальнейшего изучения. Во многих случаях я перефразировал или прямо цитировал то, что авторы должны сказать, чтобы сохранить послание и смысл, который они хотели передать.
Полезные ресурсы
- Ваши журналы GC говорят с вами, издание G1GC Кирка Пеппердина — Слайды — Видео
- Дискуссия Специальная группа по интересам — модератор Ричард Уорбертон (видео)
- Кэширование: понимайте, измеряйте и используйте ваш кэш процессора более эффективно » @RichardWarburto — (видео и слайды)
- Статья об операциях атомного ввода-вывода (Linux) Джонатана Корбета
- Статьи и презентации о Azul Zing, GC с низкой задержкой и OpenJDK от Gil Tene (видео и слайды)
- Алгоритмы без блокировки для максимальной производительности. Автор Martin Thompson
- Пользовательская группа Performance Java — «Для опытных разработчиков Java, которые хотят вывести свои системы на новый уровень»
- Настройка размера пула потоков от Кирка Пеппердина
- Как НЕ измерить задержку по Джилу Тене
- Понимание Java сборки мусора и что вы можете с этим сделать , Гил Тене
- Vanilla #Java Понимание того, как на самом деле работает Core Java, может помочь вам в написании более простых и быстрых приложений. Автор Peter Lawrey
- Профилирование Java в производстве — Каушик Среневасан
- Шпаргалка с вариантами сборки мусора JVM от HotSpot (v3) от Алексея Рагозина
- Оптимизация компьютеров масштаба Google: опыт NUMA — авторы из Univ. Cal (SD) и Google!
- MegaPipe: новый интерфейс программирования для масштабируемого сетевого ввода-вывода нескольких авторов!
- Что каждый программист должен знать о памяти Ульриха Дреппера
- Барьеры памяти: аппаратное представление для хакеров программного обеспечения — Пол Э. МакКенни (Технологический центр Linux — IBM Beaverton)