generational-arena
generational-arena copied to clipboard
Change generation type to `NonZeroU64`
From the docs: [A NonZeroU64
is] an integer that is known not to equal zero. This enables some memory layout optimization. For example, Option<NonZeroU64>
is the same size as u64
.
I replaced generation: u64
with NonZeroU64
(initializing it to 1 rather than 0). This example shows that Index
takes 16 bytes of memory, and Option<Index>
currently takes 24 bytes, but with this optimization it would take 16 bytes like a plain Index
.
I run the benchmarks and the results are almost the same. There may be a small regression (but it could also just be a random fluctation) caused by the fact that incrementing a NonZeroU64
by 1 requires converting it to a u64
and back. If NonZeroU64
gets better support in the standard library, that may be optimized further.
Still, memory optimization is significative. I myself may need to store a large amount of Option<Index>
and I belive it's a rather common use-case, so I think it would be worth it.
The changes to the library per-se are backward-compatble (no public interface has changed). I am afraid the serde serialization is not, though: an Index
which was serialized with generation 0 would now probably produce an error when deserialized.
Is this the test you need?
On a side-note: there may be a way to implement this without breaking serialization compatibility. Serialize an Index
with generation n
as having generation n-1
, and deserialize an Index
with generation n
as having generation n+1
. It may be unnecessarily complicated though, and it has no benefits besides being backward-compatible.
NonZeroU64
now has saturating_add
, so there should be no need to convert it to a regular u64
and back anymore.