TGViewer
Евгений Козлов пишет про IT Евгений Козлов пишет про IT @careerunderhood · 2.84K subscribers
Post #441 1.68K
Concurrency, Synchronization and Consistency. Иерархия накладных расходов.

Спустя время глядя на цикл постов понял что в нем не хватило отдельного саммари c выводами о том как добавление синхронизации и согласованности влияет на производительность. Концептуальным проблемам мы посвятили достаточно времени, а перформансу можно было и побольше.

И в этот момент мне совершенно случайно попалась статья, в которой автор буквально делает тоже самое, что и я в цикле постов - препарирует шаг за шагом механизмы синхронизации и демонстрирует бенчмарки. Она и подтолкнула меня к написанию бонус-поста.

Задача - безопасно, согласованно и максимально быстро работать из нескольких потоков c переменной uint64, как со счетчиком. Бенчмарки собрать с 4 разных процессоров.

Bench №1 - Блокирующая синхронизация / атомики.

Самая наивная из возможных реализаций - использовать Mutex. Бенчмарки говорят - стоимость одной операции += для программы из 2х потоков - 125 наносекунд. И чем больше потоков тем дороже операция. Подобное поведение мы уже рассматривали в посте про нелинейную масштабируемость мьютексов.

Можно ли сделать лучше? Да, например избавиться от мьютекса и взять:
- атомарный uint64 и явно использовать Compare and Swap.
- атомарный uint64 и довериться компилятору.

Получилось неплохо, из интересного - CAS оказался на том же уровне что и мьютекс.

Bench №2 - Бутылочное горлышко системных вызовов

Автор реализует Ticket lock используя atomic + sched_yield(2) syscall. С помощью аналогичной связки я писал свой мьютекс на Go. Получается еще хуже чем в первом бенче, оно и понятно почему - больше взаимодействия с ОС. В настоящем мьютексе сделано поинтереснее, рассказывал об этом здесь и в статье про самописный mutex.

Bench №3 - Неявное переключение контекста

Автор идет дальше и предлагает 2 варианта как бы еще подступиться:
- condvar которая бы позволила засыпать и пробуждать все ожидающие потоки
- честная блокировка с очередью потоков. Почему называется честной - потому что ресурс передается строго в порядке в котором на него претендовали потоки.

Первый вариант демонстрирует проблему thundering herd, так как мы пробуждем все потоки, а захватит ресурс только один, а остальные сожгут CPU и снова уснут. Можно былои не будить вовсе.

Второй справился лучше. Ведь мы решили проблему thundering herd. Но всё равно никуда не годится, так как у этой реализации другая проблема - lock convoy.

Bench №4 - 0 переключений контекста (без учета прерываний ОС)

Что если sched_yield(2) заменить на ; и как следствие не отпускать ядро до момента пока у потока его не заберет ОС? Катастрофа и переход от наносекунд к микросекундам.

Что мы видим? С каждым бенчем все хуже и хуже. Ощущение, что лучше чем стандартный атомик сделать невозможно. Но тут автор явно говорит - хватить демонстрировать проблемы, давайте попробуем сделать что-то реально классное. И сделал.

Bench №5 - Шардируемый счетчик

Если наша цель выжать максимум из рантайма нам нужно явно избегать конкуренции между ядрами за какие либо ресурсы. И чтобы этого добиться нужно явно код программы адаптировать к нашему железу. Автор продемонстрировал реализацию счетчика которая побеждает все предыдущие бенчмарки.

-----

Если подытожить - на перформанс корректного многопоточного приложения посягают:
- мьютексы со своей нелинейной масштабируемостью по количеству ядер;
- атомики и ассемблер. CAS и FAA инструкции;
- системные вызовы к ОС;
- явные и неявные переключения контекста.
- потребность иметь в программе строгий порядок и честность (lock convoy problem).
- наличие логики создающей ситуацию когда потоки циклически пытаются захватить ресурс, но чаще терпят неудачу (thundering herd problem).

И всего этого можно избежать заплатив цену. Что автор и продемонстрировал. Предлагаю вам взглянуть на код в конце статьи и ответить в комментариях - затащили ли бы вы подобное в production?
Performance Matters A Concurrency Cost Hierarchy Concurrent operations can be grouped relatively neatly into categories based on their cost
  • 🔥 8
  • 👍 5
More from @careerunderhood
  1. Sep 30, 2026Результаты опроса меня впечатлили. Большинству интересны истории из работы. Поехали, начне…
  2. Sep 25, 2026Post #470
  3. Sep 21, 2026Concurrency, Synchronization and Consistency. Non-blocking. Оглавление Введение - Блокирую…
  4. Sep 21, 2026Concurrency and Consistency. Non-blocking, lock-free and async. Пост №12. Заключение. Когд…
  5. Sep 20, 2026Concurrency and Consistency. Non-blocking, lock-free and async. Пост №11. Самые важные фак…
  6. Sep 19, 2026Concurrency and Consistency. Non-blocking, lock-free and async. Пост №10. Продвинутые wait…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →