tgoop.com/random_rust_dev/73
Last Update:
Давненько ничего не писал. Ни тут не писал, ни на Rust.
Хватит это терпеть, как говориться.
Сегодня добавил еще одну структуру данных в свой арсенал.
Сей арсенал запакован в crate amity
(англ. peaceful relations, as between nations; friendship).
Который я и опубликовал. https://docs.rs/amity/latest/amity/
Верхнеуровневая документация хромает, но стараюсь хотя бы типы и методы задокументировать как следует.
Что есть в этой библиотеке. От простого к сложному
1. `CacheAlign и
CachePadded` позволяют выравнивать данные по краям кэш-линий, избегая ситуации false sharing.
False sharing происходит когда два потока одновременно обращаются к двум разным областям памяти, которые разделяют кэш-линию.
Один поток делает запись и инвалидирует всю кэш-линию, второй поток вынужден ее обновлять, хотя данные, которые нужны потоку вовсе не поменялись.
Предоставленные типы могут быть использованы для конструирования других конкурентных структур данных.
2. `TripleBuffer` - очень простой в использовании и эффективный single-producer single-consumer канал с емкостью очереди 1.
Особенно полезен, когда consumer читает значения и их можно переиспользовать в producer-е, экономя гига-циклы.
Например когда значения содержат ссылки на ресурсы или аллоцирую память.
К тому же producer знает, было ли значение прочитано consumer-ом или нет и обновить его соответствующе, что может дать не только бонус к производительности, но и вовсе сделать алгоритм невозможный с обычным каналом.
3. `BackOff` используется в различных алгоритмах ожидания, что бы делать сначала busy spin, переходить к более энергоэффективным thread yield и наконец остановке треда.
4. `RawSpin` - самая простая имплементация блокировки на основе busy spin. Использует BackOff. Совместим в lock_api.
5. `FlipBuffer` - кольцевой буфер с возможностью добавлять в значения параллельно и без блокировок. Но только пока вместимости хватает.
`FlipQueue` - надстройка над FlipBuffer
, которая добавляет значения под shared lock, пока хватает вместимости и делает unique lock при необходимости, а так же что бы забрать значения.
Оба варианта могут быть использованы в fork-join сценариях, где fork-и могут эффективно добавлять значения в очередь, а забираются они после join или очень редко в fork-ах.
6. `park` - модуль с абстрактным thread parking. С `std
` можно использовать Thread
и стандартный паркинг. Без std
остается thread yield. Но пользователь может использовать кастомную реализацию.
Блокирующие алгоритмы (кроме spin) могут использовать любую реализацию.
7. `PtrState и
AtomicPtrState` - комбинирует указатель и состояние в одном значении и позволяет атомарно читать и модифицировать. Неатомарная версия предоставлена для полноты.
`AtomicPtrState` занимает 1 usize
и позволяет совершать те же операции что и AtomicUsize
или AtomicPtr
. Для состояния используются биты, которые гарантируются быть нулевыми в указателе в результате выравнивания. Адрес и состояние аккуратно разделяются и смешиваются, гарантируя сохранение provenance указателя.
8. `CondVar` - классический conditional variable на основе AtomicPtrState. Все операции требуют не более одного CAS вы цикле. Может использовать любой thread parking из модуля выше.
Позволяет закодировать 8 бит состояния и обновлять, записывать, ожидать его.
И другие экспериментальные вещи.
У этого crate-а нет зависимостей кроме lock_api
для реализации трейтов из него и объявления синонимов типов.
Можно использовать с/без std
и alloc
.
Библиотеке явно не хватает серьезного тестирования, но как минимум некоторые тесты под miri она проходит.
BY Random Rust Dev
Share with your friend now:
tgoop.com/random_rust_dev/73