Creator here - haven't had a chance to write up a blog post yet! Stay tuned.
The gist of it is that we intercept the Rust linking phase and then drive `rustc` manually. There's some diffing logic that compares assembly between compiles and then a linking phase where we patch symbols against the running process. Works across macOS, Windows, Linux, iOS, Android, and WASM. On my m4 I can get 130ms compile-patch times, quite wicked stuff.
We handle the hard parts that the traditional dylib-reloading doesn't including TLS, statics, constructors, etc.
I've been posting demos of it to our twitter page (yes twitter, sorry...)
can't access the xitter posts... is the axum part using the whole of dioxus or bare axum + code reloading?
jkelleyrtp · 1h ago
There's a custom `axum::serve` equivalent we built that wraps the router construction in a hot-patchable function. When the patches are loaded, we reset the TCP connections.
It's a little specific to how dioxus uses axum today, but we plan to release an axum-only integration in the future.
modeless · 2h ago
Interesting, but the documentation makes it sound like you have to preemptively wrap all the code you think you might want to change in a special wrapper "call" function. If true that makes this a lot less appealing than existing solutions for other languages that can modify any function without special annotations.
jkelleyrtp · 1h ago
You basically need to wrap your program's `tick()` function. Otherwise you might be in the middle of malloc, hot-patch, and your struct's layout and alignment changes, and your program crashes due to undefined behavior.
The goal is that frameworks just bake `subsecond::current` into their `tick()` function and end-users get hot-patching for free.
No comments yet
weinzierl · 3h ago
Very nice. For a long time I wondered who would use hotpatching but working with large Java applications made me appreciate the possibility even if it is not 100% reliable (as it is in Java).
From the docs Subsecond looks almost perfect. The only downside I found is that (if I understood correctly) you have to modify the function call in the source code of every function you want to hotpatch.
It is a bit mitigated in that the change does not cost anything in release builds, but it still is a big thing. Do I want sprinkle my code with call for every function I might potentially have to patch in a debugging session?
jkelleyrtp · 2h ago
Creator here - you only need one `subsecond::call` to hook into the runtime and it doesn't even need to be in your code - it can be inside a dependency.
Currently Dioxus and Bevy have subsecond integration so they get automatic hot-patching without any end-user setup.
We hope to release some general purpose adapters for axum, ratatui, egui, etc.
weinzierl · 2h ago
Very nice! Thanks.
mmastrac · 5h ago
I'll have to give this a shot for some of the Rust server work I'm doing. progscrape.com uses a lot of tricks to boot quickly specifically because of the edit-compile-run cycle being slow (mostly deferred loading of indexes, etc).
My current day job @ Gel has me working on a Rust socket frontend for some pretty complex code and that could also be pretty interesting.
It seems to require that you choose a good "cutover" point in your codebase, but TBH that's probably not too hard to pick. The HTTP service handler in a webserver, the socket handlers in non-web serving code, etc.
It does appear to have a limitation where it will only allow the main crate to be hotpatched. That's less than ideal, but I suppose the convenience might justify some code structure changes to allow that.
prideout · 3h ago
Neat but I would prefer simply using a dylib for the part of my code that I want to be reloadable.
The gist of it is that we intercept the Rust linking phase and then drive `rustc` manually. There's some diffing logic that compares assembly between compiles and then a linking phase where we patch symbols against the running process. Works across macOS, Windows, Linux, iOS, Android, and WASM. On my m4 I can get 130ms compile-patch times, quite wicked stuff.
We handle the hard parts that the traditional dylib-reloading doesn't including TLS, statics, constructors, etc.
I've been posting demos of it to our twitter page (yes twitter, sorry...)
- With bevy: https://x.com/dioxuslabs/status/1924762773734511035
- On iOS: https://x.com/dioxuslabs/status/1920184030173278608
- Frontend + backend (axum): https://x.com/dioxuslabs/status/1913353712552251860
- Ratatui (tui apps): https://x.com/dioxuslabs/status/1899539430173786505
Our unfinished release notes are here:
https://github.com/DioxusLabs/dioxus/releases/tag/v0.7.0-alp...
More details to come!
It's a little specific to how dioxus uses axum today, but we plan to release an axum-only integration in the future.
The goal is that frameworks just bake `subsecond::current` into their `tick()` function and end-users get hot-patching for free.
No comments yet
From the docs Subsecond looks almost perfect. The only downside I found is that (if I understood correctly) you have to modify the function call in the source code of every function you want to hotpatch.
It is a bit mitigated in that the change does not cost anything in release builds, but it still is a big thing. Do I want sprinkle my code with call for every function I might potentially have to patch in a debugging session?
Currently Dioxus and Bevy have subsecond integration so they get automatic hot-patching without any end-user setup.
We hope to release some general purpose adapters for axum, ratatui, egui, etc.
My current day job @ Gel has me working on a Rust socket frontend for some pretty complex code and that could also be pretty interesting.
It seems to require that you choose a good "cutover" point in your codebase, but TBH that's probably not too hard to pick. The HTTP service handler in a webserver, the socket handlers in non-web serving code, etc.
It does appear to have a limitation where it will only allow the main crate to be hotpatched. That's less than ideal, but I suppose the convenience might justify some code structure changes to allow that.