Комментарии 7
- Атомарная операция прикрывается мьютексом.
- Используется
а неatomic.SwapUint64
(вам ведь результат свопа всё равно не важен).atomic.StoreUint64
А что это за конструкция #{cfg}
в fmt.Printf
? Он такое не поддерживает…
Недостает варианта и бенчмарков с использованием каналов. Мьютексы дико просаживают производительсность, когда много ядер. Он все ждут анлока и в это время курят. Атомики - не решение, потому что код превращается в лапшеобразного монстра.
Придумали же изначально идиоматический вариант, когда данные модифицирует только одна горутина и выгребает из канала инфу, а все конкурентные горутины в этот канал кидают данные и дальше выполняются без остановки, если канал буферизированный.
Внутри каналов изначально были те же мьютексы, AFAIR, так что каналы всегда работали немного медленнее мьютексов.
Да, действительно, на мьютексах. Как-то не обращал внимания на ограниченность стандартной реализации. При отправке в канал лочится (см. с 200 строки). https://github.com/golang/go/blob/master/src/runtime/chan.go
У нас просто своя кастомная реализация каналов, близкая по идеалогии к "каналам на стеройдах", которая при записи не лочится и в целом дает выгоду на 24 ядрах. По сути весь треш атомиков инкапсулирован внутри. Атомики сильно затрудняют на мой взгляд понимание кода. Пример альтернативной реализации каналов: https://docs.google.com/document/d/1yIAYmbvL3JxOKOjuCyon7JhW4cSv1wy5hC0ApeGMV9s/pub
Тем не менее, даже если в каналах (сейчас) мьютексы, мне кажется стоит писать на каналах и отдельно уделить внимание в бенчмарках этой реализации, потому что стандартные каналы могут и проапгрейдить, а мьютексы останутся как есть. Кроме того, запись в канал - отличная абстракция, которая упрощает понимание.
А разве мьютек это не есть ни что иное как небуферизированный канал?
Go: справляемся с конфликтами при блокировках с помощью пакета Atomic