Netpoll: пишем сервера, которые не умирают от нагрузки
https://habr.com/ru/companies/otus/articles/859964/
Небольшой обзор библиотеки Netpoll и гайд по использованию. Сразу отмечу, что статья хороша именно как обзор, а не как серьезный технический текст, т.к. автор статьи будто бы пытается нам её продать, делая громкие заявления, вроде таких:
Это заявление весьма преувеличено — "низкоуровневый доступ к системе" через epoll/kqueue здесь подаётся как уникальное преимущество Netpoll, хотя стандартный runtime Go тоже использует netpoller с epoll/kqueue для эффективной работы с сетевыми соединениями, да и горутины в Go достаточно легковесны (~2KB), чтобы обрабатывать множество соединений при достаточной памяти. В общем, тысяча соединений - совсем не тот порог, где net начинает "задыхаться"
Но при этом сама библиотека Netpoll и правда интересна, пусть и для каких-то особых кейсов. Она предоставляет событийно-ориентированную альтернативу стандартному подходу Go с горутинами для сетевых соединений.
Ключевые особенности:
- Не создаёт горутину на соединение — ключевое, на мой взгляд
- Напрямую работает с epoll/kqueue
- Предоставляет zero-copy API для работы с данными — т.е. позволяет работать с памятью напрямую, избегая лишнего копирования
Реальные преимущества могут быть в специфических сценариях с очень большим числом соединений и строгими требованиями к latency. Но нужны конкретные бенчмарки - в статье их, к сожалению, нет.
Для большинства задач стандартная библиотека net + встроенный netpoller будут отлично работать, вопреки драматичным заявлениям в статье о проблемах после "тысячи соединений". Хотя, автор от части тоже это признаёт, вопрос лишь в границе этого разделения:
Сама статья скорее практическая — автор показывает, как настроить Listener и EventLoop, работать с nocopy API, создать клиент и настроить мониторинг через Prometheus.
————
В любом случае, автору статьи спасибо, что подсветил эту библиотеку и передал основную суть, а также за примеры использования. Раньше я с ней не сталкивался, так что было интересно ознакомиться❤️
Буду рад, если кто-то поделится своими бенчмарками или опытом использования Netpoll в реальных проектах.
#networking #performance #netpoll
https://habr.com/ru/companies/otus/articles/859964/
Небольшой обзор библиотеки Netpoll и гайд по использованию. Сразу отмечу, что статья хороша именно как обзор, а не как серьезный технический текст, т.к. автор статьи будто бы пытается нам её продать, делая громкие заявления, вроде таких:
Если вы уже успели поиграться со стандартной библиотекой net, то знаете: она классная... до поры до времени. Как только подключений становится больше тысячи, начинается боль: блокировки, миллионы горутин и изматывающее профилирование.
А вот Netpoll решает всё это за счёт асинхронности и низкоуровневого доступа к системе. Она использует epoll на Linux и kqueue на macOS
Это заявление весьма преувеличено — "низкоуровневый доступ к системе" через epoll/kqueue здесь подаётся как уникальное преимущество Netpoll, хотя стандартный runtime Go тоже использует netpoller с epoll/kqueue для эффективной работы с сетевыми соединениями, да и горутины в Go достаточно легковесны (~2KB), чтобы обрабатывать множество соединений при достаточной памяти. В общем, тысяча соединений - совсем не тот порог, где net начинает "задыхаться"
Но при этом сама библиотека Netpoll и правда интересна, пусть и для каких-то особых кейсов. Она предоставляет событийно-ориентированную альтернативу стандартному подходу Go с горутинами для сетевых соединений.
Ключевые особенности:
- Не создаёт горутину на соединение — ключевое, на мой взгляд
- Напрямую работает с epoll/kqueue
- Предоставляет zero-copy API для работы с данными — т.е. позволяет работать с памятью напрямую, избегая лишнего копирования
Реальные преимущества могут быть в специфических сценариях с очень большим числом соединений и строгими требованиями к latency. Но нужны конкретные бенчмарки - в статье их, к сожалению, нет.
Для большинства задач стандартная библиотека net + встроенный netpoller будут отлично работать, вопреки драматичным заявлениям в статье о проблемах после "тысячи соединений". Хотя, автор от части тоже это признаёт, вопрос лишь в границе этого разделения:
Но не всё так идеально. Если вы пишете простой REST API, Netpoll вам вряд ли нужен. Зато если у вас чаты, игровые серверы, вебсокеты или TCP-прокси — это для вас.
Сама статья скорее практическая — автор показывает, как настроить Listener и EventLoop, работать с nocopy API, создать клиент и настроить мониторинг через Prometheus.
————
В любом случае, автору статьи спасибо, что подсветил эту библиотеку и передал основную суть, а также за примеры использования. Раньше я с ней не сталкивался, так что было интересно ознакомиться
Буду рад, если кто-то поделится своими бенчмарками или опытом использования Netpoll в реальных проектах.
#networking #performance #netpoll
Please open Telegram to view this post
VIEW IN TELEGRAM
Хабр
Netpoll: пишем сервера, которые не умирают от нагрузки
Вы знаете, что обычные сетевые библиотеки Go начинают « тяжело дышать », если их нагрузить десятками тысяч соединений? Неважно, делали вы HTTP API или свой TCP сервер — дефолтные инструменты вроде net...
👍26
Golang Дайджест
Netpoll: пишем сервера, которые не умирают от нагрузки https://habr.com/ru/companies/otus/articles/859964/ Небольшой обзор библиотеки Netpoll и гайд по использованию. Сразу отмечу, что статья хороша именно как обзор, а не как серьезный технический текст…
Интересное из комментов
Как пишет nuklearlord, это не первая попытка создать event-driven сетевую библиотеку для Go, предлагая альтернативу стандартному подходу "One Conn One Goroutine":
- evio first commit - Jul 4, 2017
- gnet first commit - Sep 7, 2019
- cloudwego/netpoll first commit - Feb 25, 2021
И интересный комментарий от Алексея Акуловича:
————
Также если вам интересна эта тема, стоит обратить внимание на доклад Алексея Акуловича на GopherCon Russia 2018 про ускорение TCP путём избавления от слоёв абстракций в stdlib Go. Там не было готовой либы, только примеры в репе, но объяснялось где и на чем теряем, и какие альтернативы.
#networking #performance #netpoll
Как пишет nuklearlord, это не первая попытка создать event-driven сетевую библиотеку для Go, предлагая альтернативу стандартному подходу "One Conn One Goroutine":
- evio first commit - Jul 4, 2017
- gnet first commit - Sep 7, 2019
- cloudwego/netpoll first commit - Feb 25, 2021
nuklearlord:
Между тем ключевой вопрос - как прикрутить TLS, не могут решить годами (в том числе потому, что стек TLS в Go нужно переписывать под асинхрон):
https://github.com/tidwall/evio/issues/28 "TLS support ?" - Nov 13, 2018
https://github.com/panjf2000/gnet/issues/16 "TLS support ?" - Sep 24, 2019
И без вот этого TLS не получится написать высокопроизводительные аналоги nginx или unbound... И про "focus on scenarios like Redis, HAProxy" тоже самое, TLS там же тоже не нужен...
И интересный комментарий от Алексея Акуловича:
AterCattus:
У меня тоже в 2017 была первая попытка (весьма успешная) самописной оберки поверх epool, ибо встренное ну никуда не годилось. Потом еще несколько реинкарнаций.
Но в наше время как раз таки сменился фокус на grpc, ибо по работе примерно все общение сервисов на нем, а реализация в google.golang.org/grpc отвратительна по эффективности (на GoFunc рассказывал подробности и что можно сделать).
P.S. У Go несколько лет назад (сейчас, емнип, уже исправили) при работе http2 на каждое соединение уходило по три горутины. Весело было, когда нужно хотя бы 100к коннектов держать.
————
Также если вам интересна эта тема, стоит обратить внимание на доклад Алексея Акуловича на GopherCon Russia 2018 про ускорение TCP путём избавления от слоёв абстракций в stdlib Go. Там не было готовой либы, только примеры в репе, но объяснялось где и на чем теряем, и какие альтернативы.
#networking #performance #netpoll
👍19🔥8❤4
Готовим слайсы в Go: подробно о динамических массивах, строчках и ускорении
https://habr.com/ru/companies/yadro/articles/874480/
Ещё одна неплохая и очень подробная статья про слайсы с глубоким погружением.
Что разобрано:
- Внутреннее устройство слайсов и как растёт их capacity. Также затронут интересный момент про округление вместимости из-за особенностей хранения объектов в хипе, про который редко пишут
- Разные способы создания слайсов и когда какой вариант лучше (пустой слайс,
- Передача слайсов в функции: по значению vs по указателю
- Работа со строками, конкатенация и оптимизации компилятора
- Подробный разбор
- Тонкости копирования при
- Использование
- Сравнение разных способов конкатенации строк на больших и маленьких объёмах данных
И много ещё интересного.
Особенно порадовали бенчмарки в конце с неожиданными результатами — strings.Join() может работать эффективнее чем bytes.Buffer.
В общем, рекомендую к прочтению👾
#performance #slices #strings #article
https://habr.com/ru/companies/yadro/articles/874480/
Ещё одна неплохая и очень подробная статья про слайсы с глубоким погружением.
Что разобрано:
- Внутреннее устройство слайсов и как растёт их capacity. Также затронут интересный момент про округление вместимости из-за особенностей хранения объектов в хипе, про который редко пишут
- Разные способы создания слайсов и когда какой вариант лучше (пустой слайс,
make(len)
, make(0, cap)
и т.д.).- Передача слайсов в функции: по значению vs по указателю
- Работа со строками, конкатенация и оптимизации компилятора
- Подробный разбор
bytes.Buffer
vs strings.Builder
и их особенностей- Тонкости копирования при
[]byte → string
и обратно- Использование
sync.Pool
для переиспользования памяти — как не забыть "вернуть" объект в пул и почему со strings.Builder
это не работает- Сравнение разных способов конкатенации строк на больших и маленьких объёмах данных
И много ещё интересного.
Особенно порадовали бенчмарки в конце с неожиданными результатами — strings.Join() может работать эффективнее чем bytes.Buffer.
В общем, рекомендую к прочтению
#performance #slices #strings #article
Please open Telegram to view this post
VIEW IN TELEGRAM
Хабр
Готовим слайсы в Go: подробно о динамических массивах, строчках и ускорении
Привет, Хабр! Меня зовут Владислав Белогрудов, я работаю в команде разработки интерфейсов и сервисов управления в YADRO. Мой текущий проект — информационная система на Go. В рамках проекта я...
🔥21👍11❤9
Как ускорить свой код с помощью системы непрерывного профилирования Perforator
https://habr.com/ru/companies/yandex/articles/875070
Perforator — это система непрерывного профилирования, которую разработали в Яндексе и недавно выложили в опенсорс. Да, проект написан на C++, а не на Go, но тут интересен сам инструмент, а не его исходный код.
Что интересного рассказывают в статье:
– Как работает Perforator и как его использовать
– Как интерпретировать результаты профилирования
– Как оптимизировать код на основе данных профилирования
А чем интересен сам Perforator:
- Система умеет профилировать как компилируемые языки (C++, Go, Rust), так и интерпретируемые (Python 3.12+)
- Поддерживает FDO (Feedback-driven optimization) — можно автоматически использовать профили для оптимизации новых сборок. По бенчмаркам даёт до 10% прироста производительности
- Интересная фича — профилирование по срезам для A/B-тестов через thread-local теги
- Можно использовать как распределённо (в K8s), так и локально вместо perf record
Из ограничений:
- Нужен root (CAP_SYS_ADMIN)
- Только Linux 5.4+ на x86-64
- ARM пока в разработке
- На больших хостах может съедать несколько GB RAM
————
Зачем мне это, если у нас в Go есть pprof?
Очень полезно смотреть, какие ещё бывают решения, хотя бы в образовательных целях, и не зацикливаться на чём-то одном.
А здесь можно глянуть визуализацию работы сервиса✨
#profiling #performance #ebpf #opensource
https://habr.com/ru/companies/yandex/articles/875070
Perforator — это система непрерывного профилирования, которую разработали в Яндексе и недавно выложили в опенсорс. Да, проект написан на C++, а не на Go, но тут интересен сам инструмент, а не его исходный код.
Что интересного рассказывают в статье:
– Как работает Perforator и как его использовать
– Как интерпретировать результаты профилирования
– Как оптимизировать код на основе данных профилирования
А чем интересен сам Perforator:
- Система умеет профилировать как компилируемые языки (C++, Go, Rust), так и интерпретируемые (Python 3.12+)
- Поддерживает FDO (Feedback-driven optimization) — можно автоматически использовать профили для оптимизации новых сборок. По бенчмаркам даёт до 10% прироста производительности
- Интересная фича — профилирование по срезам для A/B-тестов через thread-local теги
- Можно использовать как распределённо (в K8s), так и локально вместо perf record
Из ограничений:
- Нужен root (CAP_SYS_ADMIN)
- Только Linux 5.4+ на x86-64
- ARM пока в разработке
- На больших хостах может съедать несколько GB RAM
————
Зачем мне это, если у нас в Go есть pprof?
Очень полезно смотреть, какие ещё бывают решения, хотя бы в образовательных целях, и не зацикливаться на чём-то одном.
А здесь можно глянуть визуализацию работы сервиса
#profiling #performance #ebpf #opensource
Please open Telegram to view this post
VIEW IN TELEGRAM
Хабр
Perforator: новая система непрерывного профилирования теперь в опенсорсе
Привет! Сегодня мы выложили в опенсорс Perforator — систему непрерывного профилирования (continuous profiling), которую используем внутри Яндекса для анализа производительности...
👍16❤6🔥5🤯1
Forwarded from Cross Join - канал о разработке (Anton Okolelov)
Go планирует улучшить производительность в контейнерах (proposal)
GOMAXPROCS - это настройка в Go, которая определяет максимальное количество CPU-ядер, используемых для выполнения горутин параллельно.
В Go 1.25 разработчики предлагают встроить умный GOMAXPROCS, который будет учитывать ограничения контейнера (cgroup).
Сейчас Go автоматически устанавливает GOMAXPROCS равным всем логическим ядрам на машине, что создаёт проблемы в контейнерах, где доступно меньше ресурсов. Это приводит к неэффективной работе, проблемам с производительностью и троттлингу приложения.
Проблема актуальна для всех, кто запускает Go-приложения в контейнерах (Docker, Kubernetes), и остро стоит в окружениях, где на одной машине запускается много контейнеров с ограниченными ресурсами.
Сейчас разработчики решают эту проблему ручной настройкой через переменные окружения или используя библиотеку от убера. Новое предложение добавляет в сам Go автоматическое определение ограничений CPU из cgroups и динамическое обновление GOMAXPROCS при изменении этих ограничений.
🫥 Cross Join
⠀
#golang #performance #kubernetes #docker
GOMAXPROCS - это настройка в Go, которая определяет максимальное количество CPU-ядер, используемых для выполнения горутин параллельно.
В Go 1.25 разработчики предлагают встроить умный GOMAXPROCS, который будет учитывать ограничения контейнера (cgroup).
Сейчас Go автоматически устанавливает GOMAXPROCS равным всем логическим ядрам на машине, что создаёт проблемы в контейнерах, где доступно меньше ресурсов. Это приводит к неэффективной работе, проблемам с производительностью и троттлингу приложения.
Проблема актуальна для всех, кто запускает Go-приложения в контейнерах (Docker, Kubernetes), и остро стоит в окружениях, где на одной машине запускается много контейнеров с ограниченными ресурсами.
Сейчас разработчики решают эту проблему ручной настройкой через переменные окружения или используя библиотеку от убера. Новое предложение добавляет в сам Go автоматическое определение ограничений CPU из cgroups и динамическое обновление GOMAXPROCS при изменении этих ограничений.
⠀
#golang #performance #kubernetes #docker
Please open Telegram to view this post
VIEW IN TELEGRAM
GitHub
runtime: CPU limit-aware GOMAXPROCS default · Issue #73193 · golang/go
Overview Change the Go runtime on Linux to use CPU cgroup quota limits to set the default value of GOMAXPROCS. This is a concrete proposal for the ideas discussed in #33803. I've included a lot...
🔥59❤9👍3🤯2
Как разогнать TLS на Go до 100 Gbps — опыт Kinescope
https://habr.com/ru/companies/oleg-bunin/articles/913272/
Ребята из Kinescope показывают, как они добились скорости раздачи видео в 100 Gbps на обычных 1U-серверах, используя Go и kTLS.
Что интересного:
- Перенесли TLS-шифрование из user space в ядро Linux с помощью kTLS — получили zero-copy и минимальную нагрузку на CPU (1.4% при 40 Gbps)
- Обнаружили, что Let's Encrypt по умолчанию выдаёт RSA-сертификаты. Переход на ECDSA ускорил handshake в 40 раз (с 1.6 сек до 40 мс)
- Написали минимальный патч к стандартной библиотеке Go для поддержки kTLS — всё работает через обычные интерфейсы
- Решили проблему session resumption на множестве серверов простым способом — синхронизацией ключей между машинами
Интересный момент: когда из-за ошибки в конфиге весь трафик (40 Gbps) ушёл на одну машину — и она выдержала, хотя и "молотила" 600% CPU.
————
Хорошая статья с реальными продакшн-кейсами. Авторы не стесняются рассказывать про свои косяки (история с ChaCha и бабушкафонами) и показывают конкретные метрики.
Кстати, как заметил автор, в Go уже принято решение добавить поддержку kTLS в стандартную библиотеку — issue #44506 наконец-то сдвинулся с мёртвой точки.
#article #performance #tls
https://habr.com/ru/companies/oleg-bunin/articles/913272/
Ребята из Kinescope показывают, как они добились скорости раздачи видео в 100 Gbps на обычных 1U-серверах, используя Go и kTLS.
Что интересного:
- Перенесли TLS-шифрование из user space в ядро Linux с помощью kTLS — получили zero-copy и минимальную нагрузку на CPU (1.4% при 40 Gbps)
- Обнаружили, что Let's Encrypt по умолчанию выдаёт RSA-сертификаты. Переход на ECDSA ускорил handshake в 40 раз (с 1.6 сек до 40 мс)
- Написали минимальный патч к стандартной библиотеке Go для поддержки kTLS — всё работает через обычные интерфейсы
- Решили проблему session resumption на множестве серверов простым способом — синхронизацией ключей между машинами
Интересный момент: когда из-за ошибки в конфиге весь трафик (40 Gbps) ушёл на одну машину — и она выдержала, хотя и "молотила" 600% CPU.
————
Хорошая статья с реальными продакшн-кейсами. Авторы не стесняются рассказывать про свои косяки (история с ChaCha и бабушкафонами) и показывают конкретные метрики.
Кстати, как заметил автор, в Go уже принято решение добавить поддержку kTLS в стандартную библиотеку — issue #44506 наконец-то сдвинулся с мёртвой точки.
#article #performance #tls
🔥49👍6