Реклама в Telegram-каналах DzikPic и dev.by теперь дешевле. Узнать подробности 👨🏻‍💻
Support us

Cut, cut, cut

Оставить комментарий
Cut, cut, cut
Часто ли хочется переписать что-то с чистого листа? Часто ли резрешают это сделать? Что думают QA о регрессиях? Legacy-код навязчиво предлагает готовые решения, от которых будет только хуже? Иногда хочется отказаться от привычных средств и написать по-другому. Иногда на этот шаг вынуждают обстоятельства. И под убегающим влево курсором исчезает то, что давно пора было отрезать. ImpenetrableCastleII2Задача была проста и тривиальна - снизить сетевой latency в 3 раза. Речь шла о библиотеке, которая подключалась к UDP multicast group, получала дейтаграммы, декодировала сообщения и отдавала их клиентскому коду. Декодирование и распаковка были вылизаны до предела, оставалось улучшать транспортный уровень. Существовавшая реализация базировалась на Boost.asio, выдавала 30 микросекунд на обработку одного сообщения, очень хорошо масштабировалась, не потребляла в работе много времени CPU и использовалась по умолчанию по всей библиотеке. Заказчик хотел снизить этот результат до 10 микросекунд. Поскольку речь шла о Взрослом Enterprise, оптимизацией циклов на asm никто не занимался, просто сменили сетевой API со стандартных UDP сокетов, на более быстрый, проприетарный. Всё волшебство быстрого API основывалось на сетевой карте за 1к и экспериментальных драйверах. Карточка несла на борту два SFP+ порта, два процессора и числилась в категории 10Gbit/s. На слайдах маркетинговой презентации для данной модели заявлялись цифры в 4.5 микросекунды на получение 200 байт из сети и аббревиатура HPC. Желание о 10 микросекундах казалось уже более обоснованным. API драйвера в общих чертах повторял BSD сокеты, но имел два важных отличия:
  • Сокет нужно было создавать на предварительно открытом сетевом interface с фиксированным IP
  • Операции чтения у сокета не было. Вместо этого чтение предполагалось выполнять над interface, на котором были открыты сокеты. Операция recvfrom позволяла проверить, для какого из сокетов есть дейтаграмма, и прочитать её в буфер.
Существовавшая реализация на основе Boost.asio была проста и выразительна. Вот конструктор DataReader который создаёт вектор из boost::thread и инициализирует в каждом из воркеров по собственному толстому контексту декодирования. К слову, многие из 45 Мб статически слинкованного exe были посвящены именно декодированию сообщений. Вот main-функция потока, которая ловит эксепшны и вызывает boost::io_service->run(). Столь же лаконично смотрелся и метод DataReader::connect ( и парный DataReader::disconnect), добавлявший в список обьект Connection, который открывал ip::udp::socket, вызывал async_receive() c функтором, обрабатывающим получаемые дейтаграммы. Этот функтор вызывался после получения дейтаграммы в контексте одного из потоков, вызвавших boost::io_service->run() и там происходило декодирование. Казалось достаточно просто сменить буквы в ip::udp::socket на ip::dbl::socket и лучше оно уже не стало бы никогда. Для этого нужно было всего лишь написать собственную реализацию boost::io_service поверх волшебного API. Которая была бы совместима по концептам шаблонов с различными вспомогательными частями Boost.asio, и шаблонный полиморфизм сделал бы своё дело. Результат был красив, но не порадовал. 21 микросекунда и куча ужасных hpp файлов, которые просто описывали ненужные абстракции. К сожалению, не получилось обойтись без вспомогательного потока и мьютекса. Поток висел над сетевым interface и в режиме Busy-poll выполнял операции чтения, мьютекс применялся в очереди асинхронных операций над порожденными от этого interface сокетами. Изменение конфигурации драйвера, переход на новую версию API результата не принесли. Проблема заключалась именно в толщине Boost.asio и кастомном boost::io_service. Нужно было что-то менять. Повторно перечитав документацию на API и послушав других о том, что им не нравится в существующей реализации на Boost.asio (жаловались в основном на API boost.asio, невозможность передавать в вызов boost::io_service->run() какой-либо контекст и нехорошие зависимости) - придал исходники очистительному пламени. Первым под двуручный скальпель попала собственная реализация boost::asio::io_service с вспомогательным потоком и мьютексом. За ними, всё, что начиналось с boost::asio:: . В сухом остатке оказались только потоки, и код по декодированию сообщений. В него были добавлены собственные обёртки над проприетарным API украшенные boost::scoped_ptr. Через пять часов сосредоточенной работы получился вариант, выдававший в среднем ~11 микросекунд. После непродолжительной переписки с вендором сетевой карты и по их совету просто сменили сетевой switch на более другой. В сочетании с которым их карта показывала в среднем 7.5 микросекунд на тестах нашей библиотеки.
Новый рекламный формат в наших телеграм-каналах.

Купить 500 символов за $150

Читайте также
10 курсов по C++ (июнь 2023)
10 курсов по C++ (июнь 2023)
10 курсов по C++ (июнь 2023)
С++, несмотря на свой солидный возраст, остается одним из основных языков программирования, который применется очень широко: от разработки ПО до создания игр. В сети много ресурсов, которые помогут освоить этот язык. Советуем обратить внимаение на подборку команды Digitaldefynd, котрую мы дополнили. В ней как платные, так и бесплатные ресурсы для людей с разным уровнем подготовки и знаний С++.
1 комментарий
Как оплачиваются самые популярные языки GitHub и какой прогноз
Как оплачиваются самые популярные языки GitHub и какой прогноз
Как оплачиваются самые популярные языки GitHub и какой прогноз
Google создала «убийцу» С++
Google создала «убийцу» С++
Google создала «убийцу» С++
4 комментария
С++ по последним рейтингам растет больше всех языков программирования. Кажется, время пройти курсы
С++ по последним рейтингам растет больше всех языков программирования. Кажется, время пройти курсы
С++ по последним рейтингам растет больше всех языков программирования. Кажется, время пройти курсы

Хотите сообщить важную новость? Пишите в Telegram-бот

Главные события и полезные ссылки в нашем Telegram-канале

Обсуждение
Комментируйте без ограничений

Релоцировались? Теперь вы можете комментировать без верификации аккаунта.

Комментариев пока нет.