惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Apple Machine Learning Research
Apple Machine Learning Research
S
Schneier on Security
P
Proofpoint News Feed
The Cloudflare Blog
S
SegmentFault 最新的问题
WordPress大学
WordPress大学
Hugging Face - Blog
Hugging Face - Blog
雷峰网
雷峰网
博客园 - 【当耐特】
博客园 - 叶小钗
大猫的无限游戏
大猫的无限游戏
F
Fortinet All Blogs
宝玉的分享
宝玉的分享
博客园 - 聂微东
Engineering at Meta
Engineering at Meta
G
Google Developers Blog
Know Your Adversary
Know Your Adversary
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
S
Securelist
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
C
CXSECURITY Database RSS Feed - CXSecurity.com
G
GRAHAM CLULEY
T
Threatpost
T
Threat Research - Cisco Blogs
酷 壳 – CoolShell
酷 壳 – CoolShell
C
Cisco Blogs
Cisco Talos Blog
Cisco Talos Blog
Latest news
Latest news
C
Cybersecurity and Infrastructure Security Agency CISA
L
LINUX DO - 热门话题
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
SecWiki News
SecWiki News
L
LangChain Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
The Last Watchdog
The Last Watchdog
阮一峰的网络日志
阮一峰的网络日志
Security Latest
Security Latest
P
Palo Alto Networks Blog
L
LINUX DO - 最新话题
博客园 - 司徒正美
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
P
Privacy International News Feed
N
News and Events Feed by Topic
Spread Privacy
Spread Privacy
T
Tenable Blog
有赞技术团队
有赞技术团队
MyScale Blog
MyScale Blog
aimingoo的专栏
aimingoo的专栏
AI
AI

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
Java против Go в 2026: бенчмарк через шесть лет показал другую картину
Георгий Власов · 2026-06-25 · via Все публикации подряд на Хабре

Простой

8 мин

1

Шесть лет назад я и Питер Наги задали вопрос, который был достаточно простым, чтобы быть забавным, и достаточно занудным, чтобы быть полезным: могут ли микросервисы на Java быть такими же быстрыми, как микросервисы на Go? Речь не шла о войне языков — такие споры обычно субъективны, а хуже того, отбивают желание разбираться дальше. Практический вопрос был куда у́же: если взять небольшой HTTP-сервис, аккуратно реализовать его на Go и на Java и запустить на одном железе, окажутся ли результаты в одном диапазоне производительности?

В 2020 году ответ был «да» — для небольшой нагрузки. Тогда я заметил закономерность, которую хотел проверить снова: Java становилась интереснее по мере роста нагрузки и мощности машины. Поэтому вопрос 2026 года не «проиграл ли Go?» и не «решила ли Java все свои проблемы?». Вопрос звучит иначе: для этого сервиса, на этой машине, с текущими рантаймами — что происходит при росте нагрузки и уровня конкурентности?

Репозиторий с материалами к статье: markxnelson/go-java-go-2026. В нём код сервисов, скрипты бенчмарков, исходные результаты, сводные таблицы и скрипт построения графиков.

Исходные условия

Для этого прогона использовались:

  • Go 1.26.3

  • Oracle JDK 26.0.1

  • Helidon SE 4.4.1

  • Linux на x86_64

  • Intel Xeon W-11855M, 6 ядер / 12 потоков

  • 128 ГиБ RAM

Go-сервис использует стандартный net/http-сервер из стандартной библиотеки. Без фреймворка, без middleware-стека.

Java-сервис использует Helidon SE WebServer. Helidon 4 обрабатывает запросы через virtual threads, и health-эндпоинт подтвердил, что обработка запросов действительно шла на virtual threads.

Для Java-стороны измерялись два варианта рантайма:

  • Oracle JDK JVM

  • Oracle JDK с AOT-кэшем Leyden

Этого достаточно для данного прогона. Это удерживает статью в фокусе вопроса, который я на самом деле измерял: компактный Go-сервис против компактного Java-сервиса, оба работают последовательно на одной локальной машине.

Если вдруг решите повторить эксперимент из статьи, то удобнее всего это сделать в OpenIDE. В OpenIDE реализована первоклассная поддержка Java, Go и других самых популярных языков программирования. А поддержка Docker и 300+ плагинов в маркетплейсе доступны абсолютно бесплатно.

Сервис

Оба сервиса экспоузят одинаковые эндпоинты:

GET /health  
GET /ready  
GET /api/strings/{value}  
GET /api/generated/{size}

Эндпоинт strings полезен для простых функциональных проверок. Эндпоинт generated — тот, который использовался в матрице бенчмарка.

Это различие важно.

В одном из ранних прогонов я тестировал 2 КБ входных данных, передавая 2-килобайтную строку прямо в URL-пути. Это в основном показало, как каждый роутер обрабатывает странный path-параметр. Возможно, интересно, но не то, что я хотел измерить. В финальном полном прогоне используется /api/generated/{size}, поэтому URL остаётся коротким, а нужный размер входных данных генерируется внутри обработчика.

Каждый запрос выполняет одинаковый небольшой объём работы:

  • перевод входных данных в верхний регистр

  • перевод входных данных в нижний регистр

  • разворот строки

  • вычисление CRC32-хэша

  • повторение дополнительной CRC-работы согласно WORK_FACTOR

  • возврат JSON с результатом и метаданными рантайма

Для бенчмарка WORK_FACTOR=10. Логирование запросов было отключено.

Это всё ещё небольшой синтетический сервис. Не корзина покупок, не антифрод-система и не платёжный API. У него нет базы данных, TLS, очереди, парсера JSON на входе и внешних зависимостей. Это сделано намеренно: цель — сделать горячий путь достаточно маленьким, чтобы было видно поведение рантайма и сервера.

Конфигурация бенчмарка

Позвольте мне в этой статье использовать термин «бенчмарк» немного вольно.

Раннер бенчмарка запускает один сервис, прогоняет полную матрицу, останавливает его, затем запускает следующий сервис. Go и Java не работают одновременно, поэтому они не конкурируют друг с другом за CPU или память.

В прогоне использовались следующие параметры:

payload sizes:      7, 128, 2048, 8192 bytes  
concurrency levels: 1, 6, 12, 24, 48, 96, 192  
repeats per cell:   2  
warmup per cell:    2 seconds  
measurement window: 5 seconds  
work factor:        10

Настройки рантайма были заданы явно:

Go:  
  GOMAXPROCS=12  
  GOMEMLIMIT=off  

Java JVM variants:  
  -XX:ActiveProcessorCount=12  
  -XX:MaxRAMPercentage=75  

With Leyden:  
  -XX:+UnlockDiagnosticVMOptions  
  -XX:-AOTRecordTraining  
  -XX:-AOTReplayTraining

Объединённый набор результатов, использованный в статье, лежит здесь:

results/sequential_generated_leyden_feedback_full_20260608_0700432/

В нём — исходная сводная таблица по ячейкам, таблица пиковой пропускной способности, сводная таблица для графиков и таблица конфигурации рантайма.

Маленькая настройка, которая изменила результат Java

Перед основным прогоном бенчмарка я наткнулся на странный результат.

Сервис на Helidon выглядел нормально для маленьких ответов, но при более крупных сгенерированных ответах появлялся подозрительный нижний предел задержки около 44–48 мс — когда Go-драйвер нагрузки повторно использовал персистентные HTTP/1.1-соединения. Обычный запрос через curl после прогрева такого поведения не показывал. Это было больше похоже на поведение пакетов, чем на проблему в коде приложения.

Решение было таким:

WebServer server = WebServer.builder()  
        .port(port)  
        .connectionOptions(socket -> socket.tcpNoDelay(true))  
        .routing(routing -> routing  
                .get("/health", (req, res) -> health(res))  
                .get("/ready", (req, res) -> ready(res))  
                .get("/api/strings/{value}", (req, res) -> strings(req, res, logRequests, workFactor))  
                .get("/api/generated/{size}", (req, res) -> generated(req, res, logRequests, workFactor)))  
        .build()  
        .start();

После включения tcpNoDelay(true) кейс с 2 КБ и персистентным соединением перешёл из категории «явно сломанный бенчмарк» в категорию «нормальный сервер». Именно поэтому такие тесты стоит прогонять перед тем, как писать статью: одна пропущенная настройка способна превратиться в уверенный, но неверный вывод.

Оба сервиса также явно выставляли Content-Length для JSON-ответов известного размера.

Что получилось

Короткая версия: для этого сервиса, на этой машине, Java не была просто «не хуже Go». Как только тест выходил за пределы самого маленького случая, реализация на Java часто масштабировалась лучше.

В прогоне раннер использовал 10-секундный прогрев сервиса после его запуска, плюс 10-секундный прогрев перед каждой измеряемой ячейкой. Также прогонялся Leyden-replay с диагностическими опциями, отключающими запись и replay-тренировку во время измерения.

На самом маленьком сгенерированном payload все три варианта были в одном диапазоне при низкой конкурентности. С одним воркером и payload в 7 байт Go достиг около 3 200 запросов в секунду. Обычный Oracle JDK — около 2 722 запросов в секунду, а Leyden AOT — около 3 561.

Именно такой результат люди обычно запоминают из старых споров Java против Go: Go стартует быстро, код компактный, и при низкой конкурентности всё выглядит прекрасно.

Но картина менялась с ростом конкурентности.

При 192 одновременных воркерах и том же payload в 7 байт Go достиг около 59 173 запросов в секунду. Обычный Oracle JDK — около 74 044. Leyden AOT — около 99 099.

На 128 байтах Java-варианты вышли вперёд при более высокой конкурентности. При 192 воркерах Go достиг около 40 928 запросов в секунду, обычный Oracle JDK — около 62 433, Leyden AOT — около 91 124.

На 2 КБ разрыв стал больше. Пик Go — около 16 971 запроса в секунду. Пик обычного Oracle JDK — около 39 532, Leyden AOT — около 41 604.

На 8 КБ оба варианта Java заметно опережали Go в этом локальном прогоне. Пик Go — около 6 815 запросов в секунду. Пик обычного Oracle JDK — около 15 025, Leyden AOT — около 15 493.

Таблица пиковой пропускной способности из этого прогона выглядит так:

Данные с высокой конкурентностью, на которых строится основной вывод статьи:

Это и есть интересная версия истории: кривая.

Для самого маленького кейса сервисы находятся в одном диапазоне при низкой конкурентности, но Leyden AOT отрывается на высоком конце конкурентности. По мере роста сгенерированного payload преимущество Java проявляется раньше и сильнее.

Это не значит «Java быстрее Go». Это значит, что данная реализация на Java, на этом JDK, с обработкой запросов через virtual threads в Helidon и правильной настройкой сокета, масштабировалась лучше, чем данная реализация на Go в этой конкретной локальной среде.

В этом предложении много существительных. И все они нужны.

Что дал Leyden AOT

Leyden AOT не просто ускорил каждую конфигурацию запуска — но с отключёнными опциями replay-тренировки во время измерения он существенно изменил итоговый результат.

У него была лучшая пиковая пропускная способность для каждого payload в этом прогоне. На 7 байтах пик Leyden составил около 99 099 запросов в секунду при конкурентности 192, с p95 около 6,0 мс и p99 около 9,1 мс. На 128 байтах пик — около 91 124. На 2 КБ — около 41 604. На 8 КБ — около 15 493.

Это не значит, что Leyden выигрывал постоянно. Leyden AOT показал наивысшую пропускную способность в 20 из 28 вариантах payload/конкурентность, а обычный Oracle JDK JVM выиграл оставшиеся 8. Go не выиграл ни в одной из комбинаций в финальной матрице, хотя держался близко на самых маленьких кейсах с низкой конкурентностью. Общая картина пиковой пропускной способности сместилась: Leyden AOT оказался вариантом рантайма с наивысшим пиком для каждого payload в этой матрице.

Это не разочаровывает — это полезно. Leyden AOT не магический переключатель «сделать результаты бенчмарка лучше». Он меняет поведение запуска, прогрева и рантайма так, что это нужно измерять применительно к конкретной нагрузке, которая вас интересует.

Честный итог для этой статьи такой:

Leyden AOT оказался сильнейшим в разрезе пиковой пропускной способности после того, как прогон измерения аккуратнее отделил прогрев и отключил запись/replay-тренировку Leyden во время replay. Запуск и footprint всё ещё заслуживают отдельного рассмотрения.

Что значат эти результаты

Старый простой аргумент звучал так: Go — очевидный выбор для маленьких сетевых сервисов, потому что Java слишком тяжёлая.

Этот аргумент разбивается о результаты данной статьи.

Go остаётся прекрасным выбором для маленьких сервисов. Реализация компактна. Тулчейн прост. Стандартный HTTP-сервер вполне способен. История с деплоем единым бинарником всё ещё очень привлекательна.

Современная Java тоже отлично подходит для маленьких сервисов, и у неё совсем другой набор сильных сторон. У JVM зрелый оптимизатор, богатые инструменты наблюдаемости, отличная инженерия GC и теперь массовая модель virtual threads, которая делает блокирующий серверный код заметно дешевле, чем раньше.

Helidon SE удерживает Java-сторону достаточно компактной, чтобы это сравнение не превращалось в «минимальный Go против огромного Java-фреймворка». Это компактный Java-сервис на компактном Java-сервере.

Это не значит, что я взял бы эти цифры и сделал на их основе общекорпоративную языковую политику. Пожалуйста, не делайте так. Именно так статьи с бенчмарками превращаются в офисный фольклор, а офисный фольклор — это место, куда нюансы уходят на тихую пенсию.

Практический вывод из этой статьи такой:

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

Что я измерил бы дальше

Пропускная способность — лишь часть истории.

Следующий проход должен добавить:

  • время запуска

  • использование RSS и heap

  • утилизацию CPU

  • GC-логи

  • Java Flight Recorder

  • async-profiler

  • более длинные прогоны

  • больше повторов на ячейку

  • изолированный хост для генератора нагрузки

  • лимиты контейнера

  • TLS

  • логирование запросов включённым и выключенным

  • Spring Boot

  • хотя бы одну настоящую зависимость, например вызов базы данных

Я бы также оставил урок с tcpNoDelay в чек-листе бенчмарка. Это не эффектно, но и быть неправым на 40 миллисекунд — тоже не эффектно.

Как повторить этот прогон

Собрать Java-сервис:

cd helidon-service  
JAVA_HOME=/home/mark/jdk-26.0.1 \  
PATH=/home/mark/jdk-26.0.1/bin:/home/mark/apache-maven-3.9.12/bin:$PATH \  
mvn -B -DskipTests package

Запустить последовательную матрицу:

RESULTS_DIR=/home/mark/redstack/go-java-go-2026/results/sequential_generated_$(date +%Y%m%d_%H%M%S) \  
GO_PORT=25081 \  
JAVA_PORT=25082 \  
CONCURRENCY_LEVELS="1 6 12 24 48 96 192" \  
PAYLOAD_SIZES="7 128 2048 8192" \  
REPEATS=2 \  
DURATION=5s \  
WARMUP_DURATION=2s \  
JAVA_VARIANTS="oracle-jdk-jvm oracle-jdk-leyden-aot" \  
WORK_FACTOR=10 \  
ENDPOINT_MODE=generated \  
scripts/run-sequential-matrix.sh

Раннер автоматически записывает исходные и сводные таблицы.

В чём я всё ещё уверен

Оригинальная статья не закрыла этот вопрос навсегда. Она и не должна была.

Производительность — это не только свойство языка.

Это также свойство:

  • формы железа

  • версии рантайма

  • выбора фреймворка

  • прогрева

  • логирования

  • сериализации

  • настроек сокета

  • лимитов контейнера

  • поведения GC

  • дизайна драйвера нагрузки

  • продолжительности измерения

  • «шумных соседей»

  • частей сервиса, которые не входят в ваш бенчмарк

Это было верно в 2020-м и остаётся верным в 2026-м.

Так могут ли микросервисы на Java быть такими же быстрыми, как на Go?

Для этого сервиса, на этой машине, с этими версиями — да. И по мере роста payload и конкурентности реализация на Java часто оказывалась быстрее.

Полезный следующий вопрос «с какой формой рантайма вы хотите оперировать, наблюдать, тюнить, деплоить и жить в продакшене?». Он даёт вам что измерить, что улучшить и, в удачный день, что-то, в чём стоит поменять мнение.

Уже сейчас OpenIDE позволяет разрабатывать проекты на Java, Spring, Python, Go, PHP, JavaScript и TypeScript! А поддержка Docker и 300+ плагинов доступны абсолютно бесплатно в маркетплейсе. Пробуйте российскую IDE в деле и подписывайтесь на нас в Telegram или Max, чтобы не пропустить свежие обновления и полезные материалы.