You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Simple and fast user-space RCU1 and metric collection library
Disclaimer: This is not an officially supported Google product.
This library builds on (possibly) novel concepts that allows critical
operations (fetching a RCU snapshot, updating a value in a metric) to be
atomic, lock-free and
wait-free.
Design principles
Critical operations (RCU reading a snapshot, updating a metric) are lock- and
wait-free.
Instant data propagation. An operation finished by one thread should be
immediately visible to the other involved threads. In particular:
RCU - once a call to Update finishes, all threads will observe the new
version in their Snapshot.
Metric - when Collect is called, it observes all finished past calls to
Update.
Simple - internal logic should be encapsulated.
Usage
RCU
#include"simple_rcu/rcu.h"// A central object that distributes instances of `MyType`:auto rcu = simple_rcu::Rcu<MyType>();
// Any thread can atomically update the value (can be also a `unique_ptr`,// which auto-converts to `shared_ptr`). This is a relatively slow operation// (takes a lock internally).
rcu.Update(std::make_shared<MyType>(...));
// Fetch the most recently `Update`d value. This is a wait-free operation.// See benchmark `BM_SnapshotSharedPtrThreadLocal` below.
std::shared_ptr<MyType> ptr = rcu.Snapshot();
Metrics
#include"simple_rcu/lock_free_metric.h"// A central object that collects values of a given type.
simple_rcu::LockFreeMetric<absl::int128> metric;
// Any thread can increment the metric using a very fast, wait-free `Update`// operation:
metric.Update(42);
metric.Update(73);
// Some other thread can collect the metrics accumulated by all threads that// called `Update` before. This also resets the thread-local numbers back to 0.
std::vector<absl::int128> collected = metric.Collect();
// `collected` will now contain a single value of 42+73.
The numbers /1/ or /4/ after a benchmark name denote the number of
concurrent running threads performing the opposite operation - updates when
benchmarking reads and vice versa.
As shown below, reads are very fast and their performance suffers neither
from running concurrent read (1 to 3) nor update (1 or 4) threads.
Updates are much slower, as expected. Since (unlike reads) they acquire a
standard mutex, lock
contention occurs when there are multiple concurrent update operations. Also,
when there are multiple concurrent readers, updates become slower, since they
need to distribute values to the readers' thread-local copies.
Add bindings/implementations in other languages of your choice.
Improve documentation where needed. This project should ideally have also
some didactical value.
Popularize the project to be useful to others too. In particular there seems
to be just a copy-left (LGPLv2.1) user-space C++ RCU library
https://liburcu.org/, so having this one under a more permissive license could
be attractive for many projects.
Footnotes
If you like RCU, you might also like rCUP - a reusable coffee cup made from recycled single-use paper cups. ↩