Description
What problem does this solve or what need does it fill?
A common design pattern in bevy is the "allocate once Vec
".
Some systems require a Vec
to accumulate values, we want to avoid allocating or re-allocating the Vec
when pushing to it. Especially, we want to avoid allocating the Vec
every frame. So we store it in a Local
, clear()
it at the start of the system and use it, without worrying for allocation.
fn my_system(
// ...
mut store: Local<Vec<Foo>>,
) {
store.clear();
for foo in &query {
store.push(foo.bar());
}
// do something with store
}
This is in fact a pattern found at least twice in the bevy codebase.
A major limitation of this pattern is burst events where store
contains many Foo
s one frame every minutes or so. It will clog memory for the entirety of the runtime of the application, while staying empty most of the time.
Since it's a common pattern, we can legitimately worry that if this pattern is repeated enough time, we will see too much memory being sat on while not being used.
What solution would you like?
Creating a system parameter encapsulating this pattern makes it discoverable, so that people can learn and grab the low hanging fruits of optimization. It is also a good place to warn users of the potential pitfalls of such a pattern.
I see a few options:
- Have an actual "Preallocated" system param with a convenient API specifically made for this use case, without memory management, but advising users to be careful about memory management
- Have this system param type, and a "smart" inter-frame allocator with inter-frame awareness. This feels like the kind of problem domain already largely explored and where it should be possible to find good heuristic.
- provide a
Allocator
system param, is that even possible? lol - Add a "design pattern" section to the theoretical future bevy book