Skip to content

Hot patching systems with subsecond #19309

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

Open
wants to merge 17 commits into
base: main
Choose a base branch
from

Conversation

mockersf
Copy link
Member

Objective

Solution

  • First commit is the naive thin layer
  • Second commit only check the jump table when the code is hot patched instead of on every system execution
  • Depends on subsecond: Typed HotFn pointer DioxusLabs/dioxus#4153 for a nicer API, but could be done without
  • Everything in second commit is feature gated, it has no impact when the feature is not enabled

Testing

  • Check dependencies without the feature enabled: nothing dioxus in tree
  • Run the new example: text and color can be changed

@alice-i-cecile alice-i-cecile added this to the 0.17 milestone May 20, 2025
@alice-i-cecile alice-i-cecile added X-Controversial There is active debate or serious implications around merging this PR M-Needs-Release-Note Work that should be called out in the blog due to impact A-Dev-Tools Tools used to debug Bevy applications. labels May 20, 2025
Copy link
Contributor

It looks like your PR has been selected for a highlight in the next release blog post, but you didn't provide a release note.

Please review the instructions for writing release notes, then expand or revise the content in the release notes directory to showcase your changes.

Copy link
Member

@janhohenheim janhohenheim left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding the documentation on how to setup your system (i.e. download CLI, change linker, etc.) from https://github.com/TheBevyFlock/bevy_simple_subsecond_system :)

@janhohenheim janhohenheim added the S-Needs-Review Needs reviewer attention (from anyone!) to move forward label May 20, 2025
mockersf and others added 2 commits May 20, 2025 13:47
Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>
@jakkos-net
Copy link
Contributor

jakkos-net commented May 20, 2025

Just tried this on Linux with 2 of my existing projects. All I had to do was enable the feature and run with dx serve --hot-patch and all systems would hot-patch. Great stuff!

@janhohenheim
Copy link
Member

Little update: https://github.com/TheBevyFlock/bevy_simple_subsecond_system now supports changing the signatures of systems at runtime. Would be nice if this PR did so too, but I'm also fine with leaving that for a follow-up :)

@cart cart moved this to Respond (With Priority) in @cart's attention May 20, 2025
@MrGVSV
Copy link
Member

MrGVSV commented May 20, 2025

The future is now

Co-authored-by: JMS55 <47158642+JMS55@users.noreply.github.com>
Copy link
Contributor

@bushrat011899 bushrat011899 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple notes more than anything else. Really awesome to see this working, this will be a massive selling point of 0.17

@@ -140,6 +140,11 @@ where
})
}

#[inline]
fn refresh_hotpatch(&mut self) {
// TODO: support exclusive systems
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a particular blocker that made exclusive systems harder to implement?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, mostly I wanted to make sure we wanted to go in this direction before doing more work.

it should also be a todo that can be picked up by anyone among the many other things that can be continued if we get this first step in

Comment on lines +85 to +86
/// Refresh the inner pointer based on the latest hot patch jump table
fn refresh_hotpatch(&mut self);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// Refresh the inner pointer based on the latest hot patch jump table
fn refresh_hotpatch(&mut self);
/// Refresh the inner pointer based on the latest hot patch jump table
#[cfg(feature = "hotpatching")]
fn refresh_hotpatch(&mut self) {}

If we provide a default implementation (no-op), we can safely feature-gate this method while keeping features purely additive. I think this is desirable, as the inner implementation for a user's refresh_hotpatch might only make sense when the feature is enabled, potentially forcing them to add their own gate within the body of the function.

Alternatively, could this function be modified to be more general? E.g., refresh?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't want to cfg-gate all the functions in all the implementation of that trait, but it makes sense...

Before trying to find a more general version, let's wait for systems as entities

Comment on lines +752 to +761
// SAFETY:
// - this is not safe
// - no way
// - nu uh
// - not even marked as unsafe, that's how unsafe this is
// - enjoy
#[cfg(feature = "hotpatching")]
let out = subsecond::HotFn::current(<F as SystemParamFunction<Marker>>::run)
.try_call_with_ptr(self.current_ptr, (&mut self.func, input, params))
.expect("Error calling hotpatched system. Run a full rebuild");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfection. Should probably try to improve this before it's merged tho.

// Connects to the dioxus CLI that will handle rebuilds
// On a successful rebuild the CLI sends a `HotReload` message with the new jump table
// When receiving that message, update the table and send a `HotPatched` message through the channel
connect(move |msg| {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

subsecond seems to provide hot-reload handler, could it be used here?

use dioxus_devtools::{connect_subsecond, subsecond::register_handler};

...
        connect_subsecond();
        register_handler(Arc::new(move || {
            sender.send(HotPatched).unwrap();
        }));

Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>
@janhohenheim
Copy link
Member

janhohenheim commented May 21, 2025

Update again: I added an opt-in to rerun hot-patched systems to the prototype. This makes it way nicer to edit UIs live, as it means we can just rerun regular setup systems that are typically in OnEnter or Startup. Which breaks their run contracts, but I think that's fine as long as it's opt-in per function.
Not sure if we want to land that in the MVP, just pointing out that this possibility exists :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Dev-Tools Tools used to debug Bevy applications. M-Needs-Release-Note Work that should be called out in the blog due to impact S-Needs-Review Needs reviewer attention (from anyone!) to move forward X-Controversial There is active debate or serious implications around merging this PR
Projects
Status: Respond (With Priority)
Development

Successfully merging this pull request may close these issues.

Support hotpatching systems
8 participants