-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Optimize Semantic
's structs-of-arrays and make API simpler
#11
Comments
NB: Before attempting any perf improvements to semantic, we should tackle oxc-project/oxc#4270 first, so we can validate that these "improvements" do actually improve things. |
https://crates.io/crates/soa_derive looks like a good start, though not sure if it implements all the optimizations listed above. |
oxc-project/oxc#4208 converted the 2 |
Wow, just realized you thought of this optimization a long time ago! That's great. |
@DonIsaac suggested changes to API to hide away the struct-of-arrays approach as an implementation detail in oxc-project/oxc#4372. @rzvxa said in oxc-project/oxc#4372 (comment):
|
Semantic
's structs-of-arraysSemantic
's structs-of-arrays and make API simpler
I found this which doesn't use multiple lengths on each vector. It does most of the optimizations we want. https://github.com/tim-harding/soa-rs There is also soa-vec which doesn't use proc macros, This crate uses nightly for its allocations but we can create such a thing with our own APIs. It has an interesting approach using generics similar to how tuple types are defined in the Rust standard library. I'm also doing a small experiment on how it would look if we use declarative macros to create Soa types. It would be more verbose than any approach using procedural macros, because of soa! {
@vec(Things)
@ref(ThingRef)
struct Thing {
pub a: u32,
b: Vec<u32>,
c: Box<u32>,
d: bool,
}
}
// usage
let thing1 = Thing { a: 42, b: vec![42], c: Box::from(42), d: true };
let thing2 = Thing { a: 420, b: vec![420], c: Box::from(420), d: true };
let mut things = Things::new();
things.push(thing1);
things.push(thing2);
// only this method is `pub` similar to the field definition.
// `VecLike` can be a slice here.
let a_vec: &VecLike<u32> = things.a();
let b_vec: &VecLike<Vec<u32>> = things.b();
let c_vec: &VecLike<Box<u32>> = things.c();
let d_vec: &VecLike<bool> = things.d();
for thing in things {
let ThingRef { a, b, c, d } = thing;
} As you can see, the definition isn't as neat as options using a |
@aapoalas suggested https://crates.io/crates/parallel_vec on Discord. |
#67 is also relevant. |
Problem
Semantic
uses a struct of arrays pattern forScopeTree
and other structures.If we do oxc-project/oxc#4269, then
ScopeTree
would be purely a collection ofIndexVec
s. Then we can optimize it.At present we treat all 6 x
IndexVec
s as independent. When creating a scope, we push to each vec independently.This is inefficient in 3 ways:
len
andcapacity
are stored 6 times. They only need to be stored once, as they're the same for all 6 vecs.IndexVec::push
looks uplen
for that vec, checks if it's at capacity, and grows if required. These lookups/checks happen 6 times, when they only need to happen once.Potential solution
Find a crate which optimizes SOA structures to avoid these penalties. Hopefully one exists, but if not, create one.
The text was updated successfully, but these errors were encountered: