-
-
Notifications
You must be signed in to change notification settings - Fork 73
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
improvement(runtime): add benchmarks for and optimise struct field marshalling #238
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
)struct
struct
struct
struct
Based on profiling two optimisations were made:
const fn
s)StructRef
with a shared reference to theRuntime
instead 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
root
function if you want to hold on to theStructRef
. This turns theStructRef
into aRootedStruct
. Usage would look like this:To avoid unsafe code, there is also a safe
by_ref
function.Caveats
retry
orwait
on 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_ref
by including atoken
inRuntime
that 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
.