Open ianks opened 1 year ago
I tried 2 different approaches to this with similar performance (the commits have bench result):
Vec<Value>
and use RArray::from_slice
: cb6125b1e556b487538073a24904e7202a2d2041After comparing them, I realized they both suffer from an issue though: converting a wasmtime::Val
into a Ruby object may trigger GC and crash (see these tests for a repro case). My understanding is that with this diff, we have an RArray
on the stack that contains invalid Value
s, thus crash. In the other approach, we have unrooted Value
s on the heap (Vec<Value>
), so GC collects them and crash.
I guess we could use the Store to temporarily save Value
s and mark them. That'll eat some of the perf benefit though, and add complexity. Not sure it's worth it.
Thoughts?
I've updated Magnus so the FromIterator
implementation appends to an array in batches which in my testing (in a totally different project) is quite a bit quicker than appending one by one.
So the for
loop in invoke
could become:
results
.into_iter()
.map(|result| result.to_ruby_value(store))
.collect::<Result<RArray, _>>()
.map(|ary| ary.as_value())
I don't think I see a benchmark for this in wasmtime-rb
, so I don't know if it'd be faster for you.
I was experimenting when making
Func#call
faster, and noticed there is a decent performance win by avoidingrb_ary_push
. It requires a bit of unsafe code, but I believe the implemntation is sound: