Live data from Hacker News

Hot-code reloading on macOS/arm64 with Zig

jakubkonka.com

31–40 of 57 posts

Re: Hot-code reloading on macOS/arm64 with Zig

#31

> Instead of having your program managed by a running side-by-side loader program, what if the compiler would “simply” update the memory of the running process? You will most inevitably think I have gone completely crazy This isn't crazy - this is how just-in-time compilers work.

It is a bit crazy if you do it for hot code reloading, though, as the logic has now changed. In the case of JIT, it may swap the bytecode but the flow of execution remains the same. Hot code reloading usually requires a different approach.

JITs also support code reloading. Eg normal Clojure(Script) workflow is based on reloading both on JVM and JS platforms. But functions are not altered mid-execution, rather your top level invocation or main loop picks up the new versions of functions from the updated namespaces after reload. This seems more reliable in face of arg function argument changes.

Re: Hot-code reloading on macOS/arm64 with Zig

#32

> Instead of having your program managed by a running side-by-side loader program, what if the compiler would “simply” update the memory of the running process? You will most inevitably think I have gone completely crazy This isn't crazy - this is how just-in-time compilers work.

A typical JIT compiler runs in the same process as the executable as part of its runtime -- it's a program modifying itself. This is describing a compiler modifying the memory of a separate running process out from underneath it.

Which does seem a little crazy, and the post doesn't go into details about how the compiler knows when it's reasonable to rewrite instructions -- it seems like you would need some runtime mechanism in the child to coordinate this, or you'd run the risk of... well, literally anything could happen, with the wrong patch at the wrong time. I feel like I might be missing something. The more I think about this the crazier it seems. :)

(And if you had this inter-process channel for coordinating changes, then the child process could also just patch itself based on messages from the compiler, removing the need for special cross-process memory-writing privileges. LiveReload for native code...)

Re: Hot-code reloading on macOS/arm64 with Zig

#33
post #8
post #2

Why not simply use MAP_JIT? There is no need to do these weird tricks, plus you’re putting your process and the rest of the system at risk by elevating privilege and using task-for-pid.

Hey, author of the article here. Thanks for the suggestion! I actually didn't know about the MAP_JIT flag to mmap before and will defo consider it. As to elevating your privs - this is just a temp solution until I work out how to add this entitlement https://developer.apple.com/documentation/bundleresources/en... to the Zig compiler. I wrote the default Zig's MachO linker from scratch and it can embed the adhoc code…

Depending on the use case, you might want to have the application opt-in to the reload anyway (e.g. with before/after lifecycle callbacks), since any threads running in that address space would need to be paused, and this might lead to nasty situations if the developer isn't in control of this.

You also wouldn't need the entitlement anymore.

Re: Hot-code reloading on macOS/arm64 with Zig

#34

I love the feature but I am a little worried about how much more complex it would make the toolchain. How many extra LOC does this add to the compiler and linker (and how big are they now)?

Compiler and linker are 186,865 lines of code. My `hcs` branch which adds hot code swapping support for Linux (a companion PoC to the author of the OP) is 328 additions and 18 deletions [1]. And about 200 lines of those are adding ptrace constants to the std lib and a simple socket server to the compiler just as a method of issuing commands while the stdio is locked up in the running application.

Crazy right?

This is because incremental compilation & linking is actually the same problem as hot code swapping! This was just a natural fallout of the design of the compiler.

Same deal with Jakub's hot code swapping branch. It's 257 additions and 9 deletions and has the same ~150 lines of adding the socket server [2].

So in answer to your question, the PoC adds about 150 lines to an 186,865 line codebase.

[1]: https://github.com/ziglang/zig/compare/hcs

[2]: https://github.com/ziglang/zig/compare/hcs-macos

Re: Hot-code reloading on macOS/arm64 with Zig

#35

Earlier quoted context omitted.

> JITs don’t need to reload code If I've inlined a method, and someone redefines that method in a language that allows that, then I'm going to need to reload that code.

Yes, but if a called function redefines its own parent, it still returns to the old code, not the new code.

That is true, but JITs nevertheless perform on-stack replacement for optimization purposes.

Re: Hot-code reloading on macOS/arm64 with Zig

#37

Awesome! vlang has it too: https://github.com/vlang/v/blob/master/doc/docs.md#hot-code-...

Nice! V does it the same way as Nim though, right? From quickly browsing over the sources, it looks like it is based on dynamic library hot swapping https://github.com/vlang/v/tree/master/vlib/v/live

Re: Hot-code reloading on macOS/arm64 with Zig

#38
post #37

Awesome! vlang has it too: https://github.com/vlang/v/blob/master/doc/docs.md#hot-code-...

Nice! V does it the same way as Nim though, right? From quickly browsing over the sources, it looks like it is based on dynamic library hot swapping https://github.com/vlang/v/tree/master/vlib/v/live

Not very familiar with the mechanism, sorry. The vlang community is very reactive, both in GH Issues and the Discord channel.

They can support you with good advice in the further developing of Zig, I'm sure! Good luck!

Re: Hot-code reloading on macOS/arm64 with Zig

#39
post #5

This seems like it would just crash or make your program get into an inconsistent state. What happens if you are executing a transaction but mid transaction your binary gets updated and your transaction now has done half of what's needed by the old version and half of what's needed by the new version. I don't think it would be that hard to get into an inconsistent state.

If that matters, you probably shouldn't be using hot code reloading regardless of the language or implementation.

> If that matters, you probably shouldn't be using hot code reloading regardless of the language or implementation.

Why not? Perhaps I'm missing the point, but can't this be mutex'd away? Or perhaps you're refering to the fact that the hot code reloading mechanism should provide the mutex implicitly?

Re: Hot-code reloading on macOS/arm64 with Zig

#40
post #21

This looks awesome for game development! Short feedback loops are a superpower.

I have implemented live reload (in a much simpler and naive way) for my little game engine/framework written in C a few years ago, as a "scene" is essentially a reloadable shared library there. When it worked it was a huge productivity booster and time saver indeed, but I've eventually stopped using this feature that much once I started relying more and more on passing function pointers around as callbacks - so thing…

Optional late binding - function pointers that go through a lookup step (string or slot) before finding their destination.
Post reply on HN