Локи на чтение [2/2] Ссылка на первый
Вторая причина. Когда ReaderLock пытается зайти в секцию и борется с другими lockами, при выходе, он должен разбудить писателей, имплементации из-за поддержки обоих парадигм обычных mutex и shared_mutex так сделаны, что будят какой-то тред вне зависимости от того, писатель он или нет. В итоге когда ReaderLock пытается зайти в секцию, на него делаются дополнительные проверки в цикле, а писатель ли он. Это скорее недоработки имплементации, существуют более хорошие ReaderLock'и, скажем CountingMutex, который имеет per cpu counters намного лучше демонстрирует scale.
Другие причины, почему стоит избегать Reader Lock на коротких секциях:
Если есть Writer Lock и он будится при выходе из Reader Lock, другие Reader Lock не могут сразу войти в секцию из-за того, что есть писатель, который тоже борется за секцию. В данном случае кто-то должен выиграть и все тратят CPU, Reader Locks сериализуются по времени, вся система деградирует.
Поэтому советы такие
1. Используйте Reader Lock только, если секция достаточно большая и писатели редкие (скажем, 5-10% от всех операций, а секция как минимум количество тредов * 200-250ns).
2. Если секции супер короткие, используйте Read-Copy-Update структуры, оверхед на память будет супер мелкий
3. Если не хотите думать, используйте всегда обычные локи и мьютексы. Оптимизируйте только, когда вы начинаете видеть проблемы.
4. Lock Free редко выход в данных ситуациях, но иногда обычные атомики являются хорошим решением
Я ускорял десятки раз на своей памяти программы заменяя Reader Locks на Writer Locks, и фиксил очень интересные баги (скажем, взятие топового элемента в LRU кеше, который на самом деле мутирует структуру).
По тому, как написать production ready mutex можно целый семестровый курс прочитать, если честно. Может быть через пару лет решусь.
[1] Мой бенчмарк
[2] Отличная статья по стоимости атомиков на современных процессорах, очень много цифр, видов кешей и прочего
[3] RSEQ Per-CPU Scale Read Counting Mutex
[4] absl::Mutex implementation
[5] RCU structures
Ссылка на первую часть
Вторая причина. Когда ReaderLock пытается зайти в секцию и борется с другими lockами, при выходе, он должен разбудить писателей, имплементации из-за поддержки обоих парадигм обычных mutex и shared_mutex так сделаны, что будят какой-то тред вне зависимости от того, писатель он или нет. В итоге когда ReaderLock пытается зайти в секцию, на него делаются дополнительные проверки в цикле, а писатель ли он. Это скорее недоработки имплементации, существуют более хорошие ReaderLock'и, скажем CountingMutex, который имеет per cpu counters намного лучше демонстрирует scale.
Другие причины, почему стоит избегать Reader Lock на коротких секциях:
Если есть Writer Lock и он будится при выходе из Reader Lock, другие Reader Lock не могут сразу войти в секцию из-за того, что есть писатель, который тоже борется за секцию. В данном случае кто-то должен выиграть и все тратят CPU, Reader Locks сериализуются по времени, вся система деградирует.
Поэтому советы такие
1. Используйте Reader Lock только, если секция достаточно большая и писатели редкие (скажем, 5-10% от всех операций, а секция как минимум количество тредов * 200-250ns).
2. Если секции супер короткие, используйте Read-Copy-Update структуры, оверхед на память будет супер мелкий
3. Если не хотите думать, используйте всегда обычные локи и мьютексы. Оптимизируйте только, когда вы начинаете видеть проблемы.
4. Lock Free редко выход в данных ситуациях, но иногда обычные атомики являются хорошим решением
Я ускорял десятки раз на своей памяти программы заменяя Reader Locks на Writer Locks, и фиксил очень интересные баги (скажем, взятие топового элемента в LRU кеше, который на самом деле мутирует структуру).
По тому, как написать production ready mutex можно целый семестровый курс прочитать, если честно. Может быть через пару лет решусь.
[1] Мой бенчмарк
[2] Отличная статья по стоимости атомиков на современных процессорах, очень много цифр, видов кешей и прочего
[3] RSEQ Per-CPU Scale Read Counting Mutex
[4] absl::Mutex implementation
[5] RCU structures
Ссылка на первую часть