I don't know how to express the question in Rust, so I will express what we do in go first.
There's a common pattern to batch allocate some items in go, like this:
s := make([]*Item, n)
for i := 0; i < n; i++ {
s[i] = new(Item)
}
This will allocate n times and the address of the Items are not guaranteed to be continuous, and here's an optimized version:
s := make(map[int]*Item, n)
values := make([]Item, n)
for i := 0; i < n; i++ {
s[i] = &values[i]
}
This will only call mallocgc once and the memory layout of Items are guaranteed to be continuous, which is good for cache locality. The performance is about 2x compares to the previous version.
And here's the question: how can I do the equivalent in Rust?
I know by using let s: Vec<Item> = Vec::with_capacity(n)
will only allocate once and the memory layout is guaranteed to be continuous, but I can't find a way to do similar thing for Arc.
For example, If I use let s: Vec<Arc<Item>> = Vec::with_capacity(n)
, it will allocate space for n * Arc
, and then calling something like Arc::new(Item::default())
for n times to initialize the vec will need allocation for n times, and the memory layout are likely to be dispersed. This will lead to a great performance loss.
In async network programming, Arc<T>
is indispensable because we are always using patterns such as fan-out or spawn some task to run in the background, and lifetimes doesn't help in those cases.
I've not found a way to convert Vec<Item>
to Vec<Arc<Item>>
without extra allocation cost.