19 Dec 2020
Today I’m releasing capnproto-rust version 0.14.
The main change is a new
sync_reader
feature that allows messages to be shared between multiple threads.
With the new feature, you can, for example, wrap a capnp::message::Reader
with lazy_static
or
once_cell
and then read it from anywhere else
in your program.
Previously, doing so was not possible because the
message traversal limit
was tracked through a Cell
, causing message::Reader
to not be
Sync
.
Now, when sync_reader
is enabled, the traversal limit
is tracked through an AtomicUsize
, which can be safely
shared between threads.
To minimize the performance impact, the new implementation uses
Ordering::Relaxed
when accessing the atomic counter.
When I measured the performance on a few benchmarks,
I was initially discouraged because
fetch_sub()
seemed to be slowing things down significantly.
Fortunately, I found that splitting fetch_sub()
into separate load()
and store()
steps recovered the lost time.
(Such a split may cause the read limiter to undercount reads,
but we are okay with that level of imprecision.)
With the most recent version,
I am unable to detect any speed difference between the new atomic implementation
and the old Cell
-based one.
I would have liked to unconditionally enable atomic read limiting,
but unfortunately AtomicUsize
is not available on all platforms.
For example, rustc
does not support any atomics on
riscv32i-unknown-none-elf.
(I am unsure whether that’s an inherent property of the platform,
or whether it’s an implementation hole that could be filled in later.)
@appaquet deserves credit for submitting the pull request with this change and for patiently iterating on it with me.