Один микросек - C++, low latency, concurrency, HFT
Відкрити в Telegram
Показати більше
624
Підписники
Немає даних24 години
+57 днів
+2830 день
Архів дописів
Что почитать по C++?
https://www.saminiir.com/lets-code-tcp-ip-stack-1-ethernet-arp/ - серия статей "Let's code a TCP/IP stack"
https://pthorpe92.dev/programming/systems/common-misunderstandings/ - серия статей "Common misunderstandings" по processes, tasks, async I/O.
https://eli.thegreenplace.net/2017/concurrent-servers-part-1-introduction/ - базовое "Concurrent servers" про select/epoll.
https://accu.org/journals/overload/32/182/teodorescu/ - базовый гайд про атомики "In an atomic world" от accu.
https://www.think-cell.com/en/career/devblog/cpp-needs-undefined-behavior-but-maybe-less - про UB и будущий erroneous behavior.
https://lemire.me/blog/2024/09/09/replace-stdstring-by-stdstring_view-when-you-can/ - один mega-string вместо кучи мелких от Daniel Lemire.
https://habr.com/ru/companies/pvs-studio/articles/846532/ - std::array не медленнее C-массива от PVS studio.
https://www.studyplan.dev/pro-cpp/concepts - серия доступных уроков по C++20 concepts, если еще не вкатились.
Если подумать, каких провалов я опасаюсь в работе, то это такой тип сбоев, в которых ваша торговая система набирает очень большую и нежелательную позицию. Она начинает неконтролируемо и быстро слать ордера на биржу, превышая заложенные в систему величины рисков. Такое произошло с Knight Capital (в блоге и на хабре на русском), что впоследствии привело к продаже фирмы. Всё произойдет за минуты или секунды, и уже после случившегося вы будете какое-то время только осознавать "эээ а что происходит". Либо, как вариант, баг в логике, неверные подсчёты или парсинг ответов приводит к тому, что подсчитанная позиция расходится с реальной. Вы думаете, у вас лонг на 100k, а у вас шорт на 100k, и рынок, зараза, идет вверх. Подобное случалось и со мной и с коллегами.
Второй неприятный тип сбоев: когда из-за бага торговая система простаивает. Представьте, что ваша, с любовью разработанная, фича остановила весь терминал, и фирма не зарабатывает, скажем, 5k в минуту, во всех рабочих чатах пишут ваше имя (а вы в отпуске). Понятно, что такая ситуация есть в других IT сферах, Crowdstrike подтвердит.
Третим в списке поставлю утечку приватных ключей и паролей (в результате небрежности или злого умысла сотрудников или внешней атаки). Вот вам любопытный случай c 3commas.
Предлагаю порассуждать, какие бы вы ввели механизмы, практики, правила в своем стартапе для защиты от подобных провалов? А точно хватит времени на это (в стартапе)? А точно не будет багов в самих механизмах защиты (если речь о коде)?
Если подумать, чего я опасаюсь в работе, то это такой тип сбоев, в которых ваша торговая система набирает очень большую и нежелательную позу. Она начинает неконтролируемо и быстро слать ордера на биржу, превышая заложенные в систему величины рисков. Такое произошло с Knight Capital (https://t.me/hft_dev/36 и на хабре на русском https://habr.com/ru/articles/198766/), что впоследствии привело к продаже фирмы. Всё произойдет за минуты или секунды, и уже после случившегося вы будете какое-то время только осознавать "эээ а что происходит". Либо, как вариант, баг в логике, неверные подсчёты или парсинг ответов приводит к тому, что подсчитанная позиция расходится с реальной. Вы думаете, у вас лонг на 100k, а у вас шорт на 200k, и рынок, конечно, идет вверх. Такое случилась и со мной, и с некоторыми из коллег.
Второй неприятный тип сбоев: когда из-за бага торговая система простаивает (не торгует). Представьте, что ваша с любовью выкаченная фича остановила весь деск, и фирма не зарабатывает, скажем, 5k в минуту, и во всех чатах пишут ваше имя (а вы в отпуске). Понятно, что такая ситуация есть в других IT сферах, Crowdstrike подтвердит (https://www.kaspersky.ru/blog/crowdstrike-global-cyber-outages/37918/).
Третим в списке поставлю утечку приватных ключей и паролей (в результате злого умысла или атаки). Вот вам случай c
Предлагаю порассуждать, какие бы вы ввели механизмы, практики, правила в своем стартапе для защиты от подобных провалов?
GDB позволяет вводить команды из файла
Приведу несколько примеров. Поставить breakpoint с условием:
> cat 1.gdb break my_func if (var > 10000) commands print var info locals info registers backtrace continue endПоставить одноразовый catch на write syscall:
tcatch syscall write commands printf "Syscall write\n" printf "File descriptor: %d\n", $rdi printf "Buffer: %p\n", $rsi printf "Bytes: %d\n", $rdx continue endОбъявить функцию, которая принимает адрес и ставит условный watch на этот адрес:
define my_int_watch
watch *(int*)$arg0 if *(int*)$arg0 % 3 == 0
commands
printf "New value: %d\n", *(int*)$arg0
continue
end
end
Реальные сценарии как правило чуть сложнее, т.к. дебаг символов может и не быть, условия посложнее, но для демонстрации идеи эти подходят.
Далее команды можно запустить из файла:
gdb -p 1234 -x 1.gdb
или прямо в cli:
> source 1.gdbДа, то же самое можно ввести вручную поэтапно в cli, однако ручной ввод комманд требует времени, что может быть непозволительно в уже запущенных программах, которые нельзя прерывать. GDB также умеет в Python скрипты, но на питоняке я писал только pretty-printer'ы. Кто-то использовал python в gdb?
Что я понял про ведение телеграм канала (с января 2024)
- Можно ссылку на свой канал положить в свой профиль. Смотри пример: @yukigaru.
- Очень хорошо для меня сработала публикация в Linkedin, она принесла несколько десятков новых подписчиков. Чувствую, что в этом способе привлечения для меня еще есть большой потенциал. Взаимопиар похожих каналов работает, но мне принесло умеренно (до 20, насколько помню, у "on the way to 10x engineer"). Платная реклама в инфо-канале @seniorcpp принесла мне очень мало, это того не стоило, но попробовать хотелось.
- Если вы премиум юзер, то вы можете оставлять комментарии в чужих каналах от имени своего канала.
- Простые комментарии в чужих каналах дают мне примерно +1 подписчик на комментарий. Качественные расписанные комментарии могут дать больше, но я не уделяю этому время.
- Однако некоторые каналы заранее запрещают писать от имени своего канала (в них просто нельзя выбрать свой канал). Существуют так же боты, удаляющие комментарии от чужих каналов.
- Легко отличить какой канал создан для души, а какой чисто ради заработка. Вторые пишут общую якобы полезную информацию, но по факту инфо-мусор. Используют chat gpt для контента, содержат ошибки, но при этом имеют в десять раз больше подписчиков. Доказательств нет, но возможно, что часть подписчиков - это боты, и нужны для повышения цен на рекламу.
- Развить свой блог всё еще можно, и даже без вложений. Пробуйте, если вам интересно! Если вы начинающий, то могу написать о вас. Да, у меня пока аудитория небольшая, но если у вас до 50 человек, то это имеет смысл.
- По наблюдениям, высоко востребовано высоко-профессиональное уникальное чтиво, где автор показывает мастерство, и чего нигде больше не найдешь, и хорошо заходят подборки с полезными материалами.
- Я не зарабатываю на канале, и пока не планирую. Если бы начал монетизацию, вам бы полилась реклама курсов, а мне этого не хочется.
- У меня много идей, о чем я могу написать, но не хватает времени на реализацию.
Чего я не понял, но хотел бы понять:
- Я вижу статистику по постам, например, пост со ссылками на интересные мне материалы (https://t.me/hft_dev/49) расшарили 27 раз и в это число не входит "Saved messages". Спасибо, что делитесь постами! Но все же, кто и куда forward'ит мои посты?
Взял себе новую клаву (Nuphy Airv2, brown switches, low profile) на замену предыдущей. Теперь кайфую. Пора снова писать после долгого перерыва.
Обнаружил, что Алиса теперь использует YandexGPT для ответа на несценарные вопросы. Пока ещё не придумал, как это использовать, но вот вам Алиса, пишущая на плюсах
На работе завал, придётся делегировать.
Что стоит почитать по C++? (новые статьи, заметки, новости, блогпосты, видео)
Наверное, уже все заметили: красный цвет на всех рынках. Свечи вниз, другими словами. Слив. Дамп. Крипта приняла на себя первый удар, т.к. классические фондовые биржи закрыты в выходные. Краткосрочного резкого падения рынка HFT'шники не боятся, они этого ждут: деньги зарабатываются на движениях в любую сторону. Однако, торговая инфра переходит в такое время в режим повышенной нагрузки (опасности):
- Повышенный трафик с рынка, выжирается RAM, CPU в сотку, сервисы могут начать не вывозить, очереди наполняются и переливаются, начинают тормозить сопутствующие сервисы, и т.п.
- Вы хотите много наторговать, и выжираете API rate limits.
- Логи сыпятся так быстро, что не успеваешь вычитывать. Разбираешь несколько уже часов после движения.
- API бирж начинает присылать новые виды ошибок/ответов/состояний, на которые, возможно, вы не рассчитывали.
- События с биржи могут начать вести себя непредсказумо: молчать некоторое время, иметь увеличивенные задержки, идти в другом порядке и т.п.
- Из-за большого количества событий повышаются шансы нароллить маловероятные события: спящие баги, коллизии, переполнения, совпадение событий по времени и неожиданные реордеры.
Наверное, уже все заметили: красный цвет на всех рынках. Свечи вниз другими словами. Слив. Дамп. Крипта приняла на себя первый удар, т.к. классические фондовые биржи закрыты в выходные. Как я ранее писал, торговая инфра переходит в такое время в особый режим повышенной нагрузки (опасности), но и зарабатывает выше. Краткосрочно падение рынка HFT'шники не боятся, они этого ждут: деньги зарабатываютяс на резких движениях в любую сторону. Долгосрочно - э
Alber Blanc, где я работаю, активно нанимает, и у нас несколько вкусных вакансий.
Например:
— C++ developer (Core team), core классы и сервисы, инфраструктура для быстрой торговли, обработка и пересылка маркет даты, оптимизация, взаимодействие с FPGA и т.п.
— C++ developer (Gates team), коннекторы к биржам, оптимизация сетевых подключений, работа с маркет датой, метрики и т.п.
— Network/SRE engineer, работа с различными сетями, тюнинг линукса, отлаживание проблем ОС, автоматизация сетевых задач, работа с AWS, хостами, инфра сервисами.
Нанимаем на Кипр (Лимассол), но есть офисы и в других локациях.
Особенности:
— Нет bullshit практик и траты времени, мало бюрократии, доступы выдаются быстро.
— Топы открыты, доступны, и работают наравне с нами (программируют, например), плоская структура компании.
— По оплате HFT сфера, пожалуй, самая привлекательная: приятная ЗП, полугодовые бонусы по результатам работы, оплата дежурств, если участвуешь.
— Четкие критерии успешности, быстрый результат от твоей работы.
— Работа в офисе, удалёнки нет. Не всем это подходит, но мне вполне.
— Мало документации, кое-где не хватает комментариев и читаемости/вылизанности кода.
Вы можете податься самостоятельно, а можете через меня: я посмотрю ваше резюме, дам базовые советы, если нужно, и сделаю вам рефку. Потом, если проходите, то я получаю бонус. Чего я не делаю: не рассказываю, что конкретно спрашивают на собесе (только в общих словах).
Советую не пропускать такую возможность.
Полный список тут (нужны также кванты, трейды, QA, аналитики, фронтендеры)
Про ИИ на собесах
Хотя это всё еще редкость, но всё же появляются люди, которые пользуются ИИ (Chat GPT и аналоги) во время собеседований для получения преимуществ. Подавляющее большинство собесов сейчас проводятся дистанционно, и организовать это несложно. Один раз и нам такой чел попался (хотя доказательств нет). Но как с этим бороться? У меня нет хороших решений, но вот несколько средне-всратых идей:
1) Спрашивать сложные и редкие вопросы, на которые Chat GPT не знает ответ? Однако есть сомнение, что и кандидат обязан знать ответ на такой специфичный вопрос.
2) Спрашивать вопрос, на который Chat GPT знает ответ, а нормальный кандидат не должен знать ответа.
3) Проводить серию вопросов, требующих коротких ответов (и предупредить, что ответы должны быть короткие). Мысль в том, что ИИ склонен выдавать очень длинные ответы.
4) Смотреть, как кандидат пишет программу. Делает ли мелкие ошибки? Улучшает ли программу постепенно? Корявое ли у него форматирование? Прогоняет ли тестовые данные в уме? Если да, то он нормальный.
5) Внимательно смотреть на глаза, читает ли собеседник с экрана при ответе на вопросы? Всегда просить включать камеру (и предупреждать об этом до старта собеса).
6) Звать на финальный технический собес в офис, заодно можно будет лично познакомиться, и офис показать.
7) Увольнять с испытательного срока, если не справляется с задачами.
А к вам приходили AI-cheating энтузиасты? Нужно ли с этим бороться? А вы сами пробовали так читерить?
Про ИИ на собесах
Хотя это всё еще редкость, но всё же появляются люди, которые пользуются ИИ (Chat GPT и аналоги) во время собеседований. Подавляющее большинство сейчас проводятся дистанционно, и организовать это несложно. Один раз и нам такой чел попался. Но как с этим бороться? Моё мнение (пока не подкреплённое реальным использованием):
1) Спрашивать сложные и редкие вопросы, на которые Chat GPT не знает ответ? Может быть, но у меня есть сомнение, что и кандидат должен знать ответ на такой вопрос. Чем более специфично это знание, тем меньше (даже отличных кандидатов) будут знать это.
2) Проводить серию вопросов, требующих коротких ответов (и предупредить, что ответы должны быть короткие). Мысль в том, что gpt склонен выдавать длинные ответы с простынёй рассуждений, подготовок и заключений, а к простым ответам он не готов. Можно подготовить, но только, если знаешь, что такое будет.
3) Звать на финальный технический собес в офис, заодно можно будет лично познакомиться, и офис показать.
4) Внимательно смотреть на глаза, читает
Про ИИ на собесах
Хотя это всё еще редкость, но всё же появляются люди, которые пользуются ИИ (Chat GPT и аналоги) во время собеседований. Подавляющее большинство сейчас проводятся дистанционно, и организовать это несложно. Один раз и нам такой чел попался. Но как с этим бороться? Моё мнение (пока не подкреплённое реальным использованием):
1) Спрашивать сложные и редкие вопросы, на которые Chat GPT не знает ответ? Может быть, но у меня есть сомнение, что и кандидат должен знать ответ на такой вопрос. Чем более специфично это знание, тем меньше (даже отличных кандидатов) будут знать это.
2) Проводить серию несложных вопросов, требующих коротких ответов .
Расскажи про map, что это?
Давай теперь в формате блиц ответов:
- У него есть reserve?
- Can I erase several nodes at the same time with two iterators?
2) Звать на финальный технический собес в офис, заодно можно будет лично познакомиться, и офис показать.
Про логирование и как его ускорить
Как-то раз я ускорял логгер через io_uring, т.к. скорость логгера не позволяла совмещать активную торговлю и достаточное количество информации для расследования случившихся инцидентов. Поэтому расскажу что понял на эту тему. Простое логирование состоит из 2х частей: форматирование и вывод. Различные throttle'ры, примочки, фильтры, окрашиватели рассматривать не будем.
Форматирование:
1)
std::stringstream - не стоит, не надо: это медленно.
2) std::snprintf - не стоит, не надо: медленно, не современно.
3) std::format, поддерживается только с C++20. Я его не смотрел, но подозреваю, что в текущем виде libfmt будет быстрее.
4) libfmt - базовый выбор, достаточно быстрый. Для самых критических областей добавляем FMT_COMPILE, но не повсюду.
5) Не форматировать вообще. Можно складывать бинарные данные в файл (подход Binlog), либо отправлять куда-то (но это получается уже телеметрия). Но тогда файл требует декодирования отдельной тулзой. Но это можно автоматизировать.
6) Выносить форматирование в отдельный поток. Интересный подход из Quill. Они encode'ят аргументы в буфер, и предполагается, что это быстрее, чем отформатировать. Попробую эту либу, и позже поделюсь впечатлениями.
7) Еще крайне желательно не вычислять формат аргументы, если текущий verbosity все равно не выведет эту строку. Это приводит нас к тому, что нам подходят только макросы в том месте, где юзеры вызывают логирование.
Какие есть варианты по выводу сформированной строки на file storage:
1) Вывод в файл через:
- std::ofstream::operator << и flush
- fwrite + fflush (glibc)
- один write syscall
Выдают примерно одинаковые величины задержек. По логике можно представить, что дёрнуть просто syscall дешевле, но по факту разницу сложно увидеть.
В первых двух вариантах можно не делать flush на каждую строку, это сильно быстрее (т.к. данные буферятся в юзерспейсе), но тогда:
- Если долго нет новой строчки, то последнюю можно долго не видеть в логе. Но можно дополнительно flush'ить по таймеру.
- Что-то потеряется при креше, т.к. останется в памяти процесса. Однако это можно достать из кордампа gdb-скриптюней (такое не писал, но выглядит осуществимым).
Проблемы: средняя скорость min/avg: до 1 микроса, но периодически write может сделать серьезный пик, уходя в запись на устройство на 1-5мс. Можно попробовать понастраивать механизм сбрасывания dirty pages (см. sysctl -a | grep vm.dirty_).
2) Передаём задачу записи в отдельный поток. Так делает, например, Quill. Это очень быстро (скорость: от сотни наносекунд, если используете простую очередь, mutex и cv, и несколько наносекунд, если пишете в ring buffer (если не боитесь переполнения)), но имеет свои недостатки:
- Этому отдельному потоку тоже нужно какое-то (неторговое) ядро.
- При креше вы можете потерять несколько последних строк (а именно они обычно нужны при креше). Снова можно пробовать выковыривать из крешдампа, но это неудобно.
3) Запись в ядре через io_uring: выглядит интересно, но имеет свои сложности: код надо очень аккуратно писать, понимать как настраивать kworker'ы (куда их пиннить, какие там размеры буферов и т.п.). Подходит для kernel'ов старше 5.1. В случае креша без специальных приседаний ядро не дозапишет строки. Я эту штуку использовал, и было интересно познакомиться с механизмом.
4) Запись в отдельном своём сервисе. Как ему максимально быстро передать строку - отдельный непростой вопрос, который может сильно всё усложнить. Сервисом тоже нужно управлять, деплоить, он тоже может упасть.
5) Вариант предыдущего пункта: выводить в stdout и писать в файловую систему через стандартный сервис (journald, dockerd). Тоже один syscall, поэтому по скорости как запись в файл, но без пиков в несколько миллисов. Довольно быстро, стандартно. Легко поддержать ротацию. Если процесс крашнется сразу после лог строчки, то демон всё дозапишет.[easy] Третьим будет вопрос: как лучше и как корректно: делать unlock после notify или до?
{
std::unique_lock l{_m};
_queue.push(val);
_cv.notify_one();
}
или
{
std::unique_lock l{_m};
_queue.push(val);
}
_cv.notify_one();В комментах к предыдущему вопросу были верные ответы. Продолжаем ковырять condition variables, есть ли здесь проблема?
template <typename T>
class Queue {
public:
Queue(size_t limit): _limit(limit) {}
void push(const T& val) {
std::unique_lock l{_m};
_queue.push(val);
_cv.wait(l, [&] { return !_limit || _queue.size() < _limit; });
_queue.push(val);
_cv.notify_one(); // there's at least one item!
}
T pop() {
std::unique_lock l{_m};
_cv.wait(l, [&] { return !_queue.empty(); });
auto v = std::move(_queue.front());
_queue.pop();
_cv.notify_one(); // there's at least one slot!
return v;
}
private:
std::mutex _m;
std::condition_variable _cv;
std::queue<T> _queue;
size_t _limit;
};В пятницу возник интересный вопрос:
template <typename T>
class Queue {
public:
void push(const T& val) {
std::unique_lock l{_m};
_queue.push(val);
if (_queue.size() == 1) { // was empty
_not_empty_cv.notify_one();
}
}
T pop() {
std::unique_lock l{_m};
_not_empty_cv.wait(l, [&]() {
return !_queue.empty();
});
auto v = std::move(_queue.front());
_queue.pop();
return v;
}
private:
std::mutex _m;
std::condition_variable _not_empty_cv;
std::queue<T> _queue;
};
Есть ли здесь проблема?Воркшоп на какую тему был бы интересен?
Что я понял про ведение практических вебинаров (воркшопов)?
Я провёл одну тему (condition variables) три раза с разными людьми, и вот что понял:
— практико-ориентированный подход, в котором участники пишут код прямо сейчас, востребован. Лекций, вебинаров и курсов много, а воркшопов мало.
— 3 часа это слишком, надо уклываться в 2:15 - 2:30, и делать один перерыв на 2-3 минуты (достаточно, чтобы сходить в туалет или налить чаю).
— идея с усложнениями - работает, и некоторые успевают их выполнять.
— Zoom хорошо подходит для такого формата (и, пожалуй, только он и подходит), имеет доступную цену.
— не все задачи и темы подходят для такого формата, т.к. в некоторых
— сначала у меня было 7 задач, потом я сделал 6 задач, сейчас считаю, что достаточно где-то 4-5 задач.
— со своего канала на ~300 человек без какой-либо рекламы у меня получилось привлечь ~20 участников, на конференции было 50 участников и было бы больше, но мы ограничили сверху. Если бы я постарался больше, то смог бы сам привлечь 25-30. С рекламой, полагаю, реально было бы достичь и до 60-80, но доказательств пока нет. Учтите, что вход был бесплатным, а с платным входом понадобится реклама и мощная подача.
— до конца у меня доходят примерно 50-60% участников. Надо стремиться увеличивать этот процент.
— я получил 3000 тыр со свободной цены (спасибо, Денис). Добровольная оплата - это хороший признак либо получения реальной пользы, либо эмоций. Однако ради денег делать это не получится, это всё же каких-то других целей. Получить признание, внимание, подписчиков, реализовать себя и т.п.
