Оптимизация производительности Java: восемь антипаттернов, замедляющих ваш код

✍️ OpenClawRadar📅 Опубликовано: 20 марта 2026 г.🔗 Source
Оптимизация производительности Java: восемь антипаттернов, замедляющих ваш код
Ad

Улучшение производительности за счет исправления антипаттернов

Джонатан Фогел создал приложение для обработки заказов на Java, которое изначально имело время выполнения 1198 мс, обрабатывало 85 000 заказов в секунду, использовало чуть более 1 ГБ кучи и имело 19 пауз сборки мусора. После исправления восьми антипаттернов без изменений архитектуры или обновлений JDK производительность улучшилась до 239 мс времени выполнения, 419 000 заказов в секунду, 139 МБ кучи и 4 пауз сборки мусора. Это представляет собой 5-кратную пропускную способность, на 87% меньшее использование кучи и на 79% меньше пауз сборки мусора.

Восемь антипаттернов производительности Java, которые нужно исправить

  • Конкатенация строк в циклах - O(n²) копирование из-за неизменяемости
  • Итерация потоков O(n²) внутри циклов - потоковая обработка всего списка для каждого элемента
  • String.format() в горячих путях - самый медленный построитель строк, парсинг формата при каждом вызове
  • Автоупаковка в горячих путях - миллионы одноразовых объектов-обёрток
  • Исключения для управления потоком выполнения - fillInStackTrace() проходит по всему стеку вызовов
  • Слишком широкие блокировки - одна блокировка становится узким местом
  • Пересоздание переиспользуемых объектов - ObjectMapper, DateTimeFormatter, Gson при каждом вызове
  • Прикрепление виртуальных потоков (JDK 21-23) - synchronized + блокирующий ввод-вывод прикрепляет носители
Ad

Подробные примеры и исправления

1. Конкатенация строк в циклах

Проблемный код:

String report = "";
for (String line : logLines) {
    report = report + line + "\n";
}

Это создаёт O(n²) копирование из-за неизменяемости строк. Тесты BellSoft JMH показывают, что при увеличении n в 4 раза конкатенация в цикле замедляется более чем в 7 раз.

Исправление:

StringBuilder sb = new StringBuilder();
for (String line : logLines) {
    sb.append(line).append("\n");
}
String report = sb.toString();

Примечание: Начиная с JDK 9, компилятор оптимизирует однострочную конкатенацию, например "Order: " + id + " total: " + amount, но эта оптимизация не распространяется на циклы.

2. Случайная O(n²) с потоками внутри циклов

Проблемный код:

for (Order order : orders) {
    int hour = order.timestamp().atZone(ZoneId.systemDefault()).getHour();
    long countForHour = orders.stream()
        .filter(o -> o.timestamp().atZone(ZoneId.systemDefault()).getHour() == hour)
        .count();
    ordersByHour.put(hour, countForHour);
}

Этот паттерн составлял почти 71% образцов стека ЦП в записи JFR. При 10 000 заказах он выполняет 100 миллионов сравнений вместо одного прохода.

Исправление:

for (Order order : orders) {
    int hour = order.timestamp().atZone(ZoneId.systemDefault()).getHour();
    ordersByHour.merge(hour, 1L, Long::sum);
}

Это обеспечивает производительность O(n) с одним проходом. Вы также можете использовать Collectors.groupingBy(... Collectors.counting()) в одном потоковом конвейере.

Статья является частью 1 из 3 частей серии по оптимизации производительности Java, части 2 и 3 скоро появятся. Часть 2 пройдёт через данные профилирования, стоящие за этими цифрами, включая flame graphs и то, какие методы действительно были горячими.

📖 Read the full source: HN AI Agents

Ad

👀 Смотрите также

Четыре способа переноса истории ChatGPT в память Claude
Гайды

Четыре способа переноса истории ChatGPT в память Claude

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

OpenClawRadar
OpenClaw 101: краткое руководство для начинающих
Гайды

OpenClaw 101: краткое руководство для начинающих

u/mehdiweb
Разделение контекста агента на три уровня для решения проблемы 700-строчного монолита
Гайды

Разделение контекста агента на три уровня для решения проблемы 700-строчного монолита

Команда, создающая 6-агентную автономную систему, решила проблему раздувания контекстных файлов, разделив контекст агента на три слоя на основе типа задачи и частоты изменений: CLAUDE.md для идентичности, BRIEFING.md для миссии и PLAYBOOK.md для операций. Такой подход предотвращает скрытые сбои из-за ограничений аргументов и делает редактирование предсказуемым.

OpenClawRadar
Пять распространенных проблем с конфигурацией OpenClaw, которые увеличивают расходы на API
Гайды

Пять распространенных проблем с конфигурацией OpenClaw, которые увеличивают расходы на API

В посте на Reddit определены пять проблем конфигурации в настройках OpenClaw, которые приводят к чрезмерному потреблению API-кредитов, включая использование дорогих моделей для рутинных задач, отсутствие лимитов бюджета, открытые шлюзы, неуправляемую память и непроверенные навыки.

OpenClawRadar