-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
refactor: dynamic dispatch async commands #13464
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
base: dev
Are you sure you want to change the base?
refactor: dynamic dispatch async commands #13464
Conversation
Package Changes Through 097c8d5There are 8 changes which include tauri-bundler with patch, tauri with minor, tauri-cli with patch, tauri-codegen with minor, tauri-utils with minor, @tauri-apps/api with minor, @tauri-apps/cli with patch, tauri-runtime-wry with patch Planned Package VersionsThe following package releases are the planned based on the context of changes in this pull request.
Add another change file through the GitHub UI by following this link. Read about change files or the docs at github.com/jbolda/covector |
crates/tauri/src/ipc/mod.rs
Outdated
pub fn respond_async_serialized<F>(self, task: F) | ||
where | ||
F: Future<Output = Result<InvokeResponseBody, InvokeError>> + Send + 'static, | ||
{ | ||
pub fn respond_async_serialized( | ||
self, | ||
task: Pin<Box<dyn Future<Output = Result<InvokeResponseBody, InvokeError>> + Send + 'static>>, | ||
) { |
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.
Considering that respond_async_serialized
is a pub
API, isn't this a BREAKING CHANGE?
maybe we could enable this for the debug build and still use the old static dispatch one for the release build?
In my opinion, having different signatures in debug and release modes would be confusing.
Not sure if I am correctly: if we only pass in Box::pin(...) as Pin<Box<dyn ...>>
, then only a single template instantiation of respond_async_serialized<Pin<Box<dyn ...>>>
will occur, which is effectively the same as changing the signature to Pin<Box<dyn ...>>
, right?
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.
Considering that respond_async_serialized is a pub API, isn't this a BREAKING CHANGE?
I believe this part was marked as unstable?
In my opinion, having different signatures in debug and release modes would be confusing.
That's true though, I feel like the performance hit probably won't be a problem considering this is only a pretty small part of the call chain anyways
Not sure if I am correctly: if we only pass in Box::pin(...) type, then only a single template instantiation of respond_async_serialized will occur, which is effectively the same as changing the signature to Pin<Box<dyn ...>>, right?
I believe the box itself will create a new generic variation for every closure, so this probably won't work
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.
Not entirely sure if this was marked as unstable or not, will double check that tomorrow, but since we manage it through macros, it should be easy to add a new function
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.
it's probably meant to be unstable but we only communicated that on the "parent" Invoke
struct.
honestly though? in my opinion marking anything pub
in our main tauri crate as unstable only via a doc comment is bullshit. Ideally unstable APIs should not be public, or clearly unstable (feature flag, or in an unstable
module path idk) but that's a discussion for later i guess.
Since we're working on v3 i think marking it as deprecated would be the more sensible choice here.
"working" as in praying it will somehow appear out of nowhere
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.
I am already directly using Invoke
downstream (in pytauri), so I always hope these APIs change as little as possible (v3
) 😂
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.
it's probably meant to be unstable but we only communicated that on the "parent" Invoke struct.
Yeah, I think so after checking
honestly though? in my opinion marking anything pub in our main tauri crate as unstable only via a doc comment is bullshit. Ideally unstable APIs should not be public, or clearly unstable (feature flag, or in an unstable module path idk) but that's a discussion for later i guess.
To be fair though, some of the things like generate_handler!
and generate_context!
and the related code are impossible to be stable and they still have to be public
Normally, users won't use them directly so it's fine to break, but it's probably a problem for the library authors (I pinned the tauri version in tauri-runtime-verso
, and also we can see the impact on pytauri
as well)
I am already directly using Invoke downstream (in pytauri), so I always hope these APIs change as little as possible (v3) 😂
I have tried to make a inner private function so the public API won't change from this, and it seems to only produce slightly more LLVM IR than doing it from the macro, pushed it
Thanks for the heads up @WSH032 about avoiding this breaking change!
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.
And the question is now, do we want to use this for both the debug build and the release build, or do we only do this in debug build for now, since this is done with a private inner function, we should be able to change this without any breakages
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.
I just tested this Box::pin(...) as Pin<Box<dyn ...>>
, and from the assembly output it does seem that only one instantiation of respond_async_serialized<Pin<Box<dyn ...>>>
occurs: https://godbolt.org/z/9sMMqdo1o
To be fair though, some things like
generate_handler!
andgenerate_context!
and the related code are impossible to make stable, and they still have to be public
I think I'll use #[doc(hide)]
to hide them.
And the question is now, do we want to use this for both the debug build and the release build, or do we only do this in debug build for now
I think everyone has their own preferences. Personally, I don't care about code bloat, so I would prefer using dyn
in debug mode to speed up development, and using impl
generics in release mode to optimize performance.
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.
I just tested this Box::pin(...) as Pin<Box<dyn ...>>, and from the assembly output it does seem that only one instantiation of respond_async_serialized<Pin<Box<dyn ...>>> occurs: https://godbolt.org/z/9sMMqdo1o
Interesting, we could try that as well (I do want to avoid thing inside the macro in general though, so if the inner function method works, I might prefer that one)
I think I'll use #[doc(hide)] to hide them.
We can't hide the top level macros like generate_handler!
, but we probably can hide the other ones, but to be fair, they still show up in IDEs so I'm not sure how effective would this be
I think everyone has their own preferences. Personally, I don't care about code bloat, so I would prefer using dyn in debug mode to speed up development, and using impl generics in release mode to optimize performance.
Good to know, I feel like this probably won't be a problem in terms of performance since the overhead of other things will heavily out weight the cost of this, but I'm fine with keeping it the same in release mode for now
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.
To be fair though, some of the things like generate_handler! and generate_context! and the related code are impossible to be stable and they still have to be public
Well there are exceptions to everything, it just shouldn't be the standard.
Reference: #13382
From some testing, this could speed up the compile time by ~10s (80s -> 70s) on a full debug build on my machine with a minimal tauri app setup, and reduces the incremental compilation time from ~10s to ~4s (By adding and removing a new line inside an async command)
I'm not entirely sure the performance implications of doing dynamic dispatch for those commands though, maybe we could enable this for the debug build and still use the old static dispatch one for the release build? (did this for dev only right now, we can revisit this in the future)
Some
cargo llvm-lines
outputsBefore
After
Note: the zip file contains the
cargo build --timings
HTML output, and because GitHub doesn't seem to like uploading HTML files directly, I zipped them incargo-build-timings.zip