rhaiscript / rhai

Rhai - An embedded scripting language for Rust.
https://crates.io/crates/rhai
Apache License 2.0
3.81k stars 179 forks source link

Arena/Allocator for Dynamic types #617

Open makspll opened 2 years ago

makspll commented 2 years ago

I've been browsing the code, but cannot seem to find the use for the double allocation, What's the purpose of it?

This effectively means there are three indirection layers between the consumer and the underlying type:

schungx commented 2 years ago

Size. An enum's size is the size of the largest variant (plus the discriminant). It is of vital interest to keep Dynamic as small as possible

Box<dyn Trait> is a fat pointer, meaning that it is two words long.

Box<Box<dyn Trait>> goes through an extra level of redirection, but makes the data type only one word long.

makspll commented 2 years ago

Hmm I see now!

I do wonder if it's possible to get the best of both worlds by using some sort of custom allocator/arena, and storing an allocation ID instead. Going through a custom allocator could allow for some neat optimizations with type-erased data structures etc.

schungx commented 2 years ago

Yes, an arena would be a nice addition, especially when you can serialize different script runs (e.g. you're running a single-threaded even loop that pulls events one at a time). Then each script run can use the arena which gets cleared out at the end.

schungx commented 2 years ago

But still, Rhai originally work on the assumption that trait objects are rare -- most scripts would be working with integers, strings, booleans etc.

If that's not the case, what I can do is add a feature, e.g. heavy_variants, which would remove the unnecessary level of Boxing at the expense of a larger Dynamic type. How much it would speed up remains to be benchmarked however...

Although I suspect that only your function call arguments are trait objects; all internal script code are predominantly standard types... Remember, in Rhai, every operator is a function call, so you'd want Dynamic to be small...

makspll commented 2 years ago

That's probably a fair assumption, this issue was just my first instinct so take it with a grain of salt!

I think Dynamic is a tool I'll personally use mostly for the ECS system, i.e. pulling a component from the game and then that component can be of any type. That and probably for binary operators where lhs and rhs can be many things (haven't looked how they work yet but I imagine that might be necessary).

heavy_variants could be useful but it's really hard to tell for me atm, the arena would probably be much more of a general solution,

my main worry were collection types since they seem to use Dynamic, meaning a lot of cache misses for any sort of collection type

schungx commented 2 years ago

my main worry were collection types since they seem to use Dynamic, meaning a lot of cache misses for any sort of collection type

Why? You mean a collection of Dynamic values that hold trait objects?

makspll commented 2 years ago

For example the array built-in type: https://rhai.rs/book/language/arrays.html, which is mapped from Vec<Dynamic>

schungx commented 2 years ago

Well, any collection of trait objects will necessarily involve allocations and redirections.

You can register a special collection type that holds just a particular type, plus an API to access it.

For example, you can register Vec<R> where R is any non-trait-object type. Then register the necessary indexers and methods (such as len). Then in Rhai it essentially serves as a TypedArray similar to JavaScript. This way you avoid spreading your data all over the place.

schungx commented 2 years ago

Nevertheless, I would caution that allocations does not necessarily equate cache misses. Modern memory allocators try to put similarly-sized allocations close to each other. You may find that your array items actually reside together in memory.

I did some testing over this when deciding whether to pack AST nodes into an array, but it seems that all the nodes are allocated close to each other in memory anyway and there is no net gain.

makspll commented 2 years ago

That's interesting and good to know! Anyhow I will report back with any more issues!

makspll commented 2 years ago

Actually maybe I'll leave open with another title