improvement(runtime): add benchmarks for and optimise struct field marshalling#238
Conversation
Codecov Report
@@ Coverage Diff @@
## master #238 +/- ##
==========================================
+ Coverage 78.91% 79.09% +0.18%
==========================================
Files 201 200 -1
Lines 12667 12749 +82
==========================================
+ Hits 9996 10084 +88
+ Misses 2671 2665 -6
Continue to review full report at Codecov.
|
e7282c0 to
0152450
Compare
baszalmstra
left a comment
There was a problem hiding this comment.
Very cool! But wow this involves a lot of lifetimes!
Does this mean that the wait function doesnt exist anymore? Does that mean that if you make an error in you Mun code you can only really unwrap? Do you already have a proposal on how to handle errors in Mun code?
My previous solution (with Lua) was to stop calling into Lua altogether until a reload occured. This is a more global solution where a reload could happen every frame instead of waiting for changes by blocking the entire application.
Something like this perhaps? (Im just spitting out a random idea)
let wrapped_runtime:SafeRuntime // or whatever
// dont call this method if the last execution errored out.
let value:Some<i32> = wrapped_runtime.with_runtime(|borrowed| {
// do stuff with the borrowed runtime here
return 0; // Returned value
});somewhere else (at the beginning of a frame or whatever)
wrapped_runtime.update()
6f33cf0 to
16d5812
Compare
Mun structs are marshalled as a StructRef. To make them rooted, they need to be converted to a RootedStruct. This avoids needing to reacquire the shared reference when getting, setting, and replacing struct fields
16d5812 to
9842ee1
Compare
This PR resolves issue #224, while introducing several benchmarks for tracking marshalling performance. There are two new benchmarks:
Both benchmarks are tested for:
f32)f32)structstructstructstructBased on profiling two optimisations were made:
const fns)StructRefwith a shared reference to theRuntimeinstead of aRc<RefCell<Runtime>>Especially the second optimisation is more involved, but results in the biggest performance gains:


Optimisation 2 has the added side-effect that marshalled structs are never rooted. You have to manually call the
rootfunction if you want to hold on to theStructRef. This turns theStructRefinto aRootedStruct. Usage would look like this:To avoid unsafe code, there is also a safe
by_reffunction.Caveats
retryorwaiton the result of theinvoke_fn!macro. This will have to be re-added in an alternative format.Future Work
struct(value)instances in a memory arena when they are marshalled - for further optimisation.as_refby including atokeninRuntimethat we can check to ensure that we are dealing with the same runtime that allocated thisRootedStruct. Its signature would look bepub fn as_ref<'r>(&self, &'r Runtime) -> Option<StructRef<'r>>. This might remove the need forby_ref.