Канал для поиска исполнителей для разных задач и организации мини конкурсов
Last updated 2 months, 1 week ago
На работе завал, придётся делегировать.
Что стоит почитать по C++? (новые статьи, заметки, новости, блогпосты, видео)
Наверное, уже все заметили: красный цвет на всех рынках. Свечи вниз, другими словами. Слив. Дамп. Крипта приняла на себя первый удар, т.к. классические фондовые биржи закрыты в выходные. Краткосрочного резкого падения рынка HFT'шники не боятся, они этого ждут: деньги зарабатываются на движениях в любую сторону. Однако, торговая инфра переходит в такое время в режим повышенной нагрузки (опасности):
- Повышенный трафик с рынка, выжирается RAM, CPU в сотку, сервисы могут начать не вывозить, очереди наполняются и переливаются, начинают тормозить сопутствующие сервисы, и т.п.
- Вы хотите много наторговать, и выжираете API rate limits.
- Логи сыпятся так быстро, что не успеваешь вычитывать. Разбираешь несколько уже часов после движения.
- API бирж начинает присылать новые виды ошибок/ответов/состояний, на которые, возможно, вы не рассчитывали.
- События с биржи могут начать вести себя непредсказумо: молчать некоторое время, иметь увеличивенные задержки, идти в другом порядке и т.п.
- Из-за большого количества событий повышаются шансы нароллить маловероятные события: спящие баги, коллизии, переполнения, совпадение событий по времени и неожиданные реордеры.
Alber Blanc, где я работаю, активно нанимает, и у нас несколько вкусных вакансий.
Например:
— C++ developer (Core team), core классы и сервисы, инфраструктура для быстрой торговли, обработка и пересылка маркет даты, оптимизация, взаимодействие с FPGA и т.п.
— C++ developer (Gates team), коннекторы к биржам, оптимизация сетевых подключений, работа с маркет датой, метрики и т.п.
— Network/SRE engineer, работа с различными сетями, тюнинг линукса, отлаживание проблем ОС, автоматизация сетевых задач, работа с AWS, хостами, инфра сервисами.
Нанимаем на Кипр (Лимассол), но есть офисы и в других локациях.
Особенности:
— Нет bullshit практик и траты времени, мало бюрократии, доступы выдаются быстро.
— Топы открыты, доступны, и работают наравне с нами (программируют, например), плоская структура компании.
— По оплате HFT сфера, пожалуй, самая привлекательная: приятная ЗП, полугодовые бонусы по результатам работы, оплата дежурств, если участвуешь.
— Четкие критерии успешности, быстрый результат от твоей работы.
— Работа в офисе, удалёнки нет. Не всем это подходит, но мне вполне.
— Мало документации, кое-где не хватает комментариев и читаемости/вылизанности кода.
Вы можете податься самостоятельно, а можете через меня: я посмотрю ваше резюме, дам базовые советы, если нужно, и сделаю вам рефку. Потом, если проходите, то я получаю бонус. Чего я не делаю: не рассказываю, что конкретно спрашивают на собесе (только в общих словах).
Советую не пропускать такую возможность.
Полный список тут (нужны также кванты, трейды, QA, аналитики, фронтендеры)
Alberblanc
C++ Developer (Core)
We are looking for talented and experienced software engineers to develop, optimize, and support our systems and tools. And we have variety of roles for C++ developers.
Про ИИ на собесах
Хотя это всё еще редкость, но всё же появляются люди, которые пользуются ИИ (Chat GPT и аналоги) во время собеседований для получения преимуществ. Подавляющее большинство собесов сейчас проводятся дистанционно, и организовать это несложно. Один раз и нам такой чел попался (хотя доказательств нет). Но как с этим бороться? У меня нет хороших решений, но вот несколько средне-всратых идей:
1) Спрашивать сложные и редкие вопросы, на которые Chat GPT не знает ответ? Однако есть сомнение, что и кандидат обязан знать ответ на такой специфичный вопрос.
2) Спрашивать вопрос, на который Chat GPT знает ответ, а нормальный кандидат не должен знать ответа.
3) Проводить серию вопросов, требующих коротких ответов (и предупредить, что ответы должны быть короткие). Мысль в том, что ИИ склонен выдавать очень длинные ответы.
4) Смотреть, как кандидат пишет программу. Делает ли мелкие ошибки? Улучшает ли программу постепенно? Корявое ли у него форматирование? Прогоняет ли тестовые данные в уме? Если да, то он нормальный.
5) Внимательно смотреть на глаза, читает ли собеседник с экрана при ответе на вопросы? Всегда просить включать камеру (и предупреждать об этом до старта собеса).
6) Звать на финальный технический собес в офис, заодно можно будет лично познакомиться, и офис показать.
7) Увольнять с испытательного срока, если не справляется с задачами.
А к вам приходили AI-cheating энтузиасты? Нужно ли с этим бороться? А вы сами пробовали так читерить?
Про логирование и как его ускорить
Как-то раз я ускорял логгер через 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мс (это на nvme). Можно попробовать понастраивать механизм сбрасывания 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, поэтому по скорости как запись в файл, но без пиков в несколько миллисов. Довольно быстро, стандартно. Легко поддержать ротацию. Если процесс крашнется сразу после лог строчки, то демон всё дозапишет.
Дополняйте, если что, или поправьте.
Третьим будет вопрос: как лучше и как корректно: делать 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
class Queue {
public:
Queue(size_t limit): _limit(limit) {}
void push(const T& val) {
std::unique_lock l{_m};
_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 _queue;
size_t _limit;
};
```
В пятницу возник интересный вопрос:
```
template
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 _queue;
};
```
Есть ли здесь проблема?
Что я понял про ведение практических вебинаров (воркшопов)?
Я провёл одну тему (condition variables) три раза с разными людьми, и вот что понял:
— практико-ориентированный подход, в котором участники пишут код прямо сейчас, востребован. Лекций, вебинаров и курсов много, а воркшопов мало.
— 3 часа это слишком, надо уклываться в 2:15 - 2:30, и делать один перерыв на 2-3 минуты (достаточно, чтобы сходить в туалет или налить чаю).
— идея с усложнениями - работает, и некоторые успевают их выполнять.
— Zoom хорошо подходит для такого формата (и, пожалуй, только он и подходит), имеет доступную цену.
— не все задачи и темы подходят для такого формата, т.к. некоторые темы нужно обдумывать и практиковать часами, если не днями. Такое лучше оставлять на offline.
— сначала у меня было 7 задач, потом я сделал 6 задач, сейчас считаю, что достаточно где-то 4-5 задач.
— со своего канала на ~300 человек без какой-либо рекламы у меня получилось привлечь ~20 участников, на конференции было 50 участников и было бы больше, но мы ограничили сверху. Если бы я постарался больше, то смог бы сам привлечь 25-30. С рекламой, полагаю, реально было бы достичь и 60-80, но доказательств пока нет. Учтите, что вход был бесплатным, а с платным входом понадобится реклама и мощная подача.
— до конца у меня доходят примерно 50-60% участников. Надо стремиться увеличивать этот процент.
— я получил 3000 тыр со свободной цены (спасибо, Денис). Добровольная оплата - это хороший признак либо получения реальной пользы, либо эмоций. Однако ради денег делать это не получится, это всё же для каких-то других целей: получить признание, внимание, подписчиков, реализовать себя и т.п.
Дальнейшие планы:
— разработать следующий воркшоп на новую тему на август
— подумать, возможно ли сделать это не в live, чтобы больше людей могли решать задачи в свободное время
Канал для поиска исполнителей для разных задач и организации мини конкурсов
Last updated 2 months, 1 week ago