5 ms·
The thing I'm always curious with hot-reload systems is whether there's a good story for state change. What happens if a `ref`'s type is changed? Are `ref` valu
by dwohnitmok 5y ago
The thing I'm always curious with hot-reload systems is whether there's a good story for state change. What happens if a `ref`'s type is changed? Are `ref` values preserved between reloads?
EDIT: Ah I just read https://github.com/let-def/hotcaml#synchronous-and-asynchronous-frontends https://github.com/let-def/hotcaml#synchronous-and-asynchron... so it looks like at least for the synchronous `hotcaml` bit it just completely reloads from scratch so state is not preserved, but I'm curious then how the `hotcaml_lwt` frontend deals with this issue.
- rsstack 5y agoCheck out how Erlang/Elixir/BEAM deal with this. Stateful processes write a state-migration function that's run (new code, old state) when hot reloading the process. Requires some forethought, especially when processes can be updated in any order, but it's really amazing. Of course, when doing hot-reloading in a local development environment and not in production, it doesn't make as much sense.
- dwohnitmok 5y agoRight Erlang has explicit migrations and dynamically-typed image-based languages just persist the state. I'm curious if there have been any similar things for statically-typed languages.
- def-lkb 5y agoI am the author of Hotcaml. There is actually some notion of persisting state in it. Reloading is done at the granularity of a module. The reverse dependencies of a module that changed are also reloaded, but the dependencies are not. The runtime state of all modules that are not reloaded is persisted. Here is an example: https://aws1.discourse-cdn.com/standard11/uploads/ocaml/original/2X/1/16dc309be61d3f54918b76bb077b846d2f61dea8.gif https://aws1.discourse-cdn.com/standard11/uploads/ocaml/orig... The dependency graph is roughly: system layer -> renderer -> slideshow The system layer initializes the window (with SDL) and an OpenGL context. The renderer allocates resources (buffers, fonts, ...). The slideshow only defines the content to be drawn. In the live code, only the slideshow is modified, so the system and renderer states are not affected. Doing reloading at the module granularity meshes well with ML semantics: it is a straightforward extension of the "hyperstatic environment" and it preserves type safety and modular abstraction. A static language that is designed with hot reloading in mind could do better, the generative nature of ML type definitions is not ideal. I guess that structural type systems permit a finer grained notion of reloading. Actually, a finer-grained notion of persistence and state migration could be built as a library (with some macros) on top of Hotcaml. The important step is to be able to reify type definitions and then to define some notion of "type compatibility" (between old and new modules) by induction on the structure of types. This is a lot of work, but could be built on top of Hotcaml foundations.
- dwohnitmok 5y ago> Reloading is done at the granularity of a module. The reverse dependencies of a module that changed are also reloaded, but the dependencies are not. The runtime state of all modules that are not reloaded is persisted. Ah that makes sense to me, and explains to me why in your linked demo the rotation resets after every color change, but the other stuff doesn't. That does mean though that having the circle not reset after every color change is probably not feasible unless the module order is fairly convoluted right? (because most straightforward ways I can think of organizing the code would have the circle motion as a reverse dependency of the color of the circle).
- def-lkb 5y ago> having the circle not reset after every color change is probably not feasible unless the module order is fairly convoluted right? Not necessarily no. The thing is that you could have an early module that implements a framework to manage state. For the circle rotation, it is quite easy, it is a single number. You could do something like: `let circle_rotation = managed_state "circle_rotation" Float 0.0` "The rotation of the circle is represented by a float initialized to 0". Then even when your module is reloaded, the hypothetical framework takes care of preserving this piece of state.
- munificent 5y agoThe Dart VM supports stateful hot reload and it's used heavily by Flutter developers. There are some kinds of structural changes that necessitate a full restart that wipes state away, but the VM is suprisingly good at migrating the existing objects in the heap to match any changes to the underlying classes and preserve as much state as possible. https://docs.flutter.dev/development/tools/hot-reload https://docs.flutter.dev/development/tools/hot-reload
- sitkack 5y agoI was going to make a similar comment about reload() in Python. One dev technique out of the many available is to have your code being edited in your editor while in another terminal window, using an ipython repl to drive it. Currently one would need to `from importlib import reload` and of course ipython itself has https://ipython.readthedocs.io/en/stable/config/extensions/autoreload.html?highlight=autoreload#autoreload https://ipython.readthedocs.io/en/stable/config/extensions/a... Launch ipython like you would `pdb` https://pypi.org/project/ipdb/ https://pypi.org/project/ipdb/ *edit to @dwohnitmok as the author of Crafting Interpreters mentioned, it really works pretty well in practice. And for cases where I was changing enough state that it bails out, you can either set a breakpoint in a test or create a little closure to build up the right state and then pass back an fn to step through in ipython. Infact, this dev style reinforces an immutable nearly functional data centric programming model. With that model, changes to code won't impact the data, so reloads are actually rare. Have shallow reference chains, use value types in simple containers and lots of problems kinda melt away. Ha! https://news.ycombinator.com/item?id=29965226 https://news.ycombinator.com/item?id=29965226 the highest rank post on Google search for that quote is less than 3 days old. Know we know why results are so bad!
- dwohnitmok 5y agoFascinating. So the main thing I'm curious about is the exact mechanics of this: > And for cases where I was changing enough state that it bails out What exactly does "bailing out" entail?
- 5y ago
- def-lkb 5y agoBoth the synchronous and asynchronous frontends preserve as much state as possible (all untouched modules are kept). They differ in the control flow they permit (the asynchronous one being more expressive). I will try to make a parallel with a simple Makefile-driven project. In the initial build, all files are built, following a topological ordering of the dependencies. For the Makefile it means invoking some unix command for each intermediate artefact. For Hotcaml, it means parsing, typing, compiling and loading each module. After that, build is incremental: when a file is modified, only this file and its reverse dependencies need to be rebuilt. Make will keep the existing artifacts that are not out of date. Hotcaml will keep the existing modules that are not out of date. And their state is preserved. Now, the synchronous frontend is quite like a regular Makefile: a build step is considered done when the build command finishes. The asynchronous frontend allows command to run in the background, like a Makefile that would spawn processes/daemon using the shell & control operator. In Hotcaml, these threads continue executing concurrently with the reloading process. They can be notified that their "host" module has been reloaded by registering with some runtime service (via a module named Hotlink).
- scoopr 5y agoAlso Visual Studio does `Edit and Continue`[0], which I believe works by patching function prologues to jump to another location.. I don't think it handles structure changes all that gracefully, but honestly I haven't used it that much to know for sure. [0] https://docs.microsoft.com/en-us/visualstudio/debugger/edit-and-continue?view=vs-2022 https://docs.microsoft.com/en-us/visualstudio/debugger/edit-...