← Back to context

Comment by jesse__

3 days ago

Strong agree here. The 'purity' BS of not modifying the running programs address space appears to come at the cost of significant programmer pain-in-the-ass. Having to hand-hold the library to maintain the indirection table is a hard no for me.

Metaprogramming that maintenance burden seems like it should be relatively straight-forward, if you've written a linker already.

The challenge is that if the program is busy in a spin loop, there's no way to preempt it and modify it. Things like malloc, spin loops, network requests, syscalls etc.

I looked into liveplusplus a lot and their unreal integration also requires a broker to get the most out of it. If you're building a game engine and want to support struct layout and alignment changes, you'll need to do some re-instancing. Hiding a `subsecond::call` deep in the bowels of the host framework hides it from the user and lets the framework handle any complicated state management it needs during hotpatches.

I wouldn't say it's purity - the first version of subsecond actually did do in-process modification - but after playing around with it for a while, I much preferred the light runtime integration. The dioxus integration was about 5 lines of code, so it's quite minimal.

  • FWIW I think the project is quite cool even if you “only” manage to roll out the subsecond integration into popular ecosystem runtimes.

    Have you considered aiming at lower level dependencies that are even more ubiquitous? Like libc functions?

    • Yeah not sure why someone's first reaction to seeing 150ms Rust hot-patches is to call it BS and a "pain-in-the-ass." Tough crowd.

      We could aim lower, or make it entirely automatic. The first prototype was entirely automatic, but I realized that you definitely need to signal to the program to hot-reload.

      For code like:

      ```rust

      while true {

          let msg = io.poll();
      

      }

      ```

      you're now stuck because the program is hung on a syscall. Doesn't matter if you hot-patch the loop, the program is stuck. My first prototype used the exception tables to unwind the program, but that didn't work on WASM and led to weird issues with cancellation and effects.

      Similar issues with one-time initialization code at the beginning of the program. You could just hot-patch from `main` - basically restarting the program - but the whole point of hot-patching is that you can keep as much state around as possible while also changing its behavior.

      For most apps, you just need one `subsecond::call()` and it works. The bevy folks wrote a `#[hot]` macro which we might integrate, but I'm also keen for frameworks to just adopt it and/or distribute a simple universal adapter.

      1 reply →