Каков ваш контрольный список разработки для Java-приложения с малой задержкой?

Я хотел бы создать исчерпывающий контрольный список для приложения Java с низкой задержкой. Можете ли вы добавить свой контрольный список здесь?

Вот мой список
1. Сделайте ваши объекты неизменяемыми
2. Постарайтесь уменьшить количество синхронизированных методов
3. Порядок блокировки должен быть хорошо задокументирован и тщательно обрабатываться
4. Используйте профилировщик
5. Используйте закон Амдала и найдите путь последовательного выполнения
6. Используйте утилиты параллелизма Java 5 и блокировки
7. Избегайте приоритетов потоков, поскольку они зависят от платформы
8. Можно использовать прогрев JVM
9. Предпочитать стратегию недобросовестной блокировки
10. Избегать переключения контекста (много потоков приводит к обратным результатам)
11. Избегать упаковки, не- boxing
12. Обратите внимание на предупреждения компилятора
13. Количество потоков должно быть равно или меньше количества ядер

Приложение с низкой задержкой настраивается на каждую миллисекунду.


person Community    schedule 04.04.2010    source источник
comment
Многие люди пишут Java-приложения с малой задержкой, время отклика которых намного меньше 1 мс. Для меня низкая задержка в Java означает менее миллисекунды.   -  person Ted Graham    schedule 22.11.2010
comment
6. используйте блокировки =› или, что еще лучше, попытайтесь сделать свой алгоритм свободным от блокировок.   -  person assylias    schedule 20.12.2012
comment
(A) Блокировка — это не плохо, соперничество — это плохо. Поймите, как избежать соперничества (без блокировки может быть хуже, если есть конфликт CAS). (В) Закон Литтла. (C) оптимизировать кеши ЦП   -  person Ben Manes    schedule 07.01.2013


Ответы (12)


Хотя неизменность — это хорошо, она не обязательно уменьшит задержку. Обеспечение низкой задержки, вероятно, зависит от платформы.

Помимо общей производительности, настройка GC очень важна. Сокращение использования памяти поможет GC. В частности, если вы можете уменьшить количество объектов среднего возраста, которые необходимо перемещать, оставьте их либо долгоживущими, либо недолговечными. Также избегайте всего, что касается перманентной завивки.

person Community    schedule 04.04.2010
comment
Хотин, не помогает ли использование неизменяемых структур данных уменьшить задержку, когда вам не нужно синхронизировать общие данные? - person Binil Thomas; 24.06.2010
comment
это, наверное, лучший ответ здесь - person bestsss; 30.05.2011

избегайте упаковки/распаковки, по возможности используйте примитивные переменные.

person Community    schedule 06.04.2010

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

person Community    schedule 10.05.2010

Покупайте, читайте и понимайте Effective Java. Также доступен в Интернете

person Community    schedule 04.04.2010

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

Если вы хотите увидеть реальное Java-приложение с малой задержкой и достаточно подробной информацией об его архитектуре, взгляните на LMAX:

Архитектура LMAX

person Community    schedule 15.05.2014

Мерить, мерить и мерить. Используйте данные, максимально приближенные к реальным, и аппаратное обеспечение, максимально приближенное к производственному, для регулярного запуска тестов. Приложения с низкой задержкой часто лучше рассматривать как устройства, поэтому вам нужно рассматривать развернутую коробку целиком, а не только конкретный метод/класс/пакет/приложение/JVM и т. д. производство.

person Community    schedule 06.01.2013

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

person Community    schedule 31.08.2012
comment
Это верно для задач с интенсивным вычислением, не обязательно для задач блокировки/ввода-вывода/других задач, где имеет смысл иметь больше потоков. Однако если у вас больше потоков, чем ядер, вам нужно будет «собрать» их так, чтобы интенсивные вычисления были закреплены отдельно от блокирующих. - person Nitsan Wakart; 06.01.2013

  • Рассмотрите возможность использования неблокирующих подходов, а не синхронизации.
  • Рассмотрите возможность использования volatile или атомарных переменных вместо блокирующих структур данных и блокировок.
  • Рассмотрите возможность использования пулов объектов.
  • Используйте массивы вместо списков, так как они более удобны для кэширования.
  • Обычно для небольших задач отправка данных на другие ядра может занять больше времени, чем обработка на одном ядре из-за блокировки и задержки доступа к памяти и кэшу. Следовательно, рассмотрите возможность обработки задачи одним потоком.
  • Уменьшите частоту обращения к основной памяти и попробуйте работать с данными, хранящимися в кешах.
  • Подумайте о выборе JIT-компилятора C2 на стороне сервера, ориентированного на оптимизацию производительности, в отличие от C1, ориентированного на быстрый запуск.
  • Убедитесь, что у вас нет ложного совместного использования полей объекта, когда два поля, используемые разными потоками, могут располагаться в одной строке кэша.
  • Читать https://mechanical-sympathy.blogspot.com/
  • Рассмотрите возможность использования UDP через TCP
person Community    schedule 04.05.2020

Используйте StringBuilder вместо String при создании больших строк. Например запросы.

person Community    schedule 04.04.2010
comment
имеет смысл только тогда, когда вы хотите что-то сделать со строкой, например. объединение других строк или реверсирование и т.п. - person Tedil; 04.04.2010
comment
Обычно это не имеет значения. Байт-коды, генерируемые компилятором Java для конкатенации строк, используют StringBuilders! - person Stephen C; 04.04.2010
comment
Конкатенация в цикле (или нескольких операторах) — это обычный случай, когда явный StringBuilder выигрывает. - person Tom Hawtin - tackline; 04.04.2010

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

Как сказал Кнут, «преждевременная оптимизация — корень всех зол».

person Community    schedule 21.04.2010
comment
Немногие из успеха или неудачи приложения зависят только от производительности. Хотя преждевременная оптимизация неправильна, это правило не подходит для каждого приложения. Приложение с низкой задержкой должно быть создано с соблюдением определенных правил. - person Mohan Narayanaswamy; 24.04.2010
comment
Мне всегда нравилось: «Сначала заставь работать, потом заставляй работать быстро». - person Oversteer; 12.11.2013
comment
Я хотел бы иметь в виду, что, сказав это, Кнут посвятил алгоритмической эффективности большую часть своей жизни. :) - person L. Blanc; 12.04.2016
comment
Имейте в виду полную цитату: мы должны забыть о небольшой эффективности, скажем, примерно в 97% случаев: преждевременная оптимизация — корень всех зол. Тем не менее, мы не должны упускать наши возможности в отношении этих критических 3%. - person Leponzo; 27.05.2021

Я думаю, что «Использовать изменяемые объекты только там, где это уместно» лучше, чем «Сделать ваши объекты неизменяемыми». Многие приложения с очень малой задержкой имеют пулы объектов, которые они повторно используют для минимизации GC. Неизменяемые объекты не могут быть повторно использованы таким образом. Например, если у вас есть класс Location:

class Location {
    double lat;
    double lon;
}

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

Однако этот подход намного сложнее, чем использование неизменяемого объекта местоположения, поэтому его следует использовать только там, где это необходимо.

person Community    schedule 12.04.2016

В дополнение к решениям уровня разработчика, уже рекомендованным здесь, также может быть очень полезно рассмотреть ускоренные среды выполнения JIT, например Zing, и решения для памяти вне кучи, такие как Teracotta BigMemory, Apache Ignite, чтобы уменьшить паузы Stop-the-world GC. Если какой-то графический интерфейс использует двоичные протоколы, такие как Hessian, ZERO-C ICE вместо веб-сервиса и т. д. очень эффективен.

person Community    schedule 03.01.2018