-
Notifications
You must be signed in to change notification settings - Fork 793
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
Hot Reload #11636
Comments
https://devblogs.microsoft.com/dotnet/introducing-net-hot-reload/
Of course F# is staying behind in terms of tooling again. 😞 |
What's the current status if:
Is hot reload able to support that currently? I.e. loading the updated assembly. |
It'll happen eventually here, but hot reload is a very new technology that is likely to undergo several changes well after .NET 6. We'll plug into it when it's more stable. |
@happypig, @charlesroddie -- |
For me personally the biggest win is with projects that we start with
"dotnet watch run". Usually those are expecto tests or asp.net core
servers. If dotnet watch run would work like fable and keep a compiler in
memory that only recompiles the stuff that is dependent on the files that I
touched, then the dev cycle could speed up dramatically.
I don't think we would need hot module replacement like webpack does - just
restart the process like dotnet watch run would do right now.
Kevin Ransom (msft) ***@***.***> schrieb am Di., 8. Juni
2021, 23:46:
… @happypig <https://github.com/happypig>, @charlesroddie
<https://github.com/charlesroddie> --
what do you want hot reload to do for you? Just asking for a feature name
is probably not going to get anything moving. We don't have plenty of other
C# features also, and we don't plan on going down the VB route of moaning
whenever we don't get some new C# feature.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#11636 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAAOANETHSOIUAQRKRF6SVLTR2FSPANCNFSM46EKO77A>
.
|
From the linked thread:
Most important is a quick development loop when changing bits of UI (likely to be MAUI with WinUI as primary development platform). For non-UI code I don't need to run code very often, sometimes only once after finishing a work item to check that it works. But for UI code a lot of tweaks and adjustments are important and need to be visualized by running the code. Hot reload would be perfect for this but does look like a very large task for F# to support Edit and Continue which it is based on. A typical UI tweak doesn't affect the API of an assembly so reference assemblies will speed up the loop. Hypothetically if it were possible, while running an application, to edit a dependent project, build it, and switch in the dll, it might capture most of the benefit of hot restart. But this may not be possible in dotnet? |
Would support for generating files for FSI scripting, like the one provided by the F# Power Pack back in the day, be an alternative in this case? Together with script debugging, of course. |
I am using blazor with fsharp. Hot reload will speed up the poductivity a lot. |
This is a critical tooling enhancement for my usage of F#. Is there some way I can contribute to move up the timeline? |
I don't think we have a full understanding of what has to be done yet. |
I decided to spelunk and get a better idea of what it takes to implement hot reload. Full notes are in this gist https://gist.github.com/farlee2121/24915fb0518ad4ca6631bc33d0ff401c Finds so far
Oustanding investigations
|
A quick update. I made an experimental fork. It's pretty basic so far
The running program will show changes, and much faster than the existing dotnet watch. A more accurate description is that rebuilding tries to output both dlls and pdbs, but those resources are already in use by the debugger process. |
@farlee2121 Don't be shy, post a GIF! |
Sorry for my ignorance, but what exactly is that demonstrating? Watch will recompile and relaunch an application today without hot reload. |
Correct. Here is the described state of my experiment I was asked to gif.
I also believe it to be faster, but my sample is only one project. While the above requirements are met with the I'm still working on demonstrating updates to F# code using existing delta appliers (true hot reload). |
I see, thank you. |
An update on my efforts.
A few other conclusions likely obvious to the FSharp team, but I had to dig for
Things I'll probably need help on if I can demonstrate a successful reload
|
I suppose @farlee2121 needs someone from Roslyn/HotReload team to join this thread |
That would certainly help |
I got a bit more work in tonight. I also set up more experiments to understand what behaviors hot reload handles for C# now. I found the results more fickle than I expected. Asp.net works fine, but I've yet to get blazor wasm working, and the console app only updates if I stop at a breakpoint. Issue ScopeMy updates have been a bit hodge-podge, so here's a summary in light of the original question: what would it take to implement hot reload for F#. I'm more confident than ever that the DeltaAppliers should be reusable for F#. "Starting in 6.0, the runtime (.NET Core and Mono) expose APIs to patch a running app". This should be language-agnostic, and addresses the complexities of different runtime conditions. My sdk fork demonstrates how to plug F# into the hot reload hierarchy. I can provide more details if needed. It's basically the single The main work to be done is an F# compiler api method that takes changed files in a project and outputs assembly patches in a format mappable to System.Reflection.Metadata.MetadataUpdater. We still need to understand that format properly. This api method should also notify when a "rude edit" that can't be handled at runtime is made so hot reload can prompt for a restart. When it's all done, we add |
Any progress so far? |
I started a new job and haven't had time for this lately. |
@dsyme can you please help on this cool feature? Do you know any Roslyn team members who can help here? |
F# support for this would be so much appreciated. I created a small repository to illustrate the problem for the new readers: https://github.com/PiotrJustyna/binoculars What I'm after is for the PID not to change as the code hot-reloads. It does work perfectly for C# 👌 I plan to use it for work where, in order to speed up deployments, we could hot swap certain F# components in our C# and F# hosts. Eagerly observing this issue 👀 |
This feature would improve our team daily workflow. I don't understand why is not being planned to introduce for F# language. It will leave the language as a second class citizen when compared with C# and even VB.NET. |
It does not make sense as it is already the .NET and needs just a piece of logic to be plugged in |
Converting F# to C# is doable with existing tools. For example, you could use something like ILSpy to decompile from IL. However, this isn't likely to enable a practical hot reload. We'd end up compiling twice and decompiling once. Much of it would likely be hard to do incrementally. It's unlikely such a pipeline would be efficient enough to beat restarting the app. It could be worth an experiment though. F# already has incremental compile capabilities. The problem is translating them into the delta format expected by the HotReload. That the delta format is not well documented right now, and not all changes are supported. We'd have to analyze the compiled code for unsupported edits. EDITI was thinking in existing tools, which probably wouldn't work. But A bit more thought, and direct transpilation to C# might not be such a bad idea. We'd have to take a look at Fabel to see how much work it is to map the AST. If we can preserve incremental compiles and feed those to a MSBuildWorkspace, which could also detect incremental changes.... it might be fast enough and offload concern for rude edit detection |
I also mean not using decompile from IL, but using the same logic as they use in incremental F# to JavaScript Fable compilation. Giraffe is built on top of ASP.NET Core, and so it receives all updates made in ASP.NET Core for free (like 50-100% speed increase in .NET 5). In the same way, if F# was also built on top of C#, so to speak (i.e. compiled to C#), as a side experiment, it сould receive hot reload and any other potential benefits which C# will definitely receive in future. These are just thoughts, they may or may not be feasible... |
@farlee2121 Hey! I know it's a lot of time since you've touched this topic but I'd like to ask you anyway. In net6 dotnet watch was working for C# projects that reference F# projects. For examlpe: new blazor server project -> reference to new F# class library project. Run dotnet watch, change somethig in C#/razor markup -> hot reload applies. Change something in F# -> rebuild. So it's okay'ish. In net7 they somehow changed workspace thingy so in the same situation any change to cs/razor files now trigger full rebuild. Did you have to implement specific F# project loader and friends? I think I will have to check out your fork because it became quite sad to use C# + F# combos. |
@dsyme @vzarytovskii Any plans doing this in Net8? Would be cool to have an option to at least change methods/let functions compiled to methods. UI frameworks are usually based on methods. |
No, no concrete plans as for now, we would certainly like to get this working, but it will need to get some proper planning and framing. As for now it's unknown what will be involved. I suspect a bunch of work will intersect with expression evaluator. |
@En3Tho I didn't get so far as a special project loader. The biggest outstanding risk was generating the deltas. Delta generation ended up a much larger and more opaque problem than expected, so I dropped the project. The Ionide proj-info project is probably your best starting place. The F# team explicitly chose not to own a project system. There are some Roslyn workspace integrations as part of the VS tooling, but I think those were getting project trees handed in from an external source I couldn't trace. It's been a while though. That's as best as I remember. There may be more project system research info in my notes if you're willing to dig |
@vzarytovskii @farlee2121 Thanks. |
I'm using Blazor C# with F# driving the business logic, in fact, F# accounts for roughly 75% of the product. Because of the existence of fsproj, it puts the hot reload into rude edit mode, which I pick 'always' to restart the application whenever I get a rude edit. At that point, it'll just refresh the page whenever I change my code. When editing the F# code, I have to stop everything and restart the application. To move on and get the benefits of hot-reload, I made a Vue project using Vue CLI, where I created a component library. Each time I approve a component in Vue, I convert it to the Blazor application. The components are nearly identical, except for the programming nuance. I was going to get on the Bolero train, but don't ask me why I'm not using it... it's a good project, though. |
Hot reload is still on the radar, however it showed to be much harder than anticipated. |
@sksallaj82 presence of F# forcing rude edits is partly a .Net 7 regression. Before this C# code could be easily edited w/o rude edits even while having a dependency on F# project. dotnet/sdk#28998 One of ways to work around this thing is to fork sdk repo and do some tweaks as I suggested in this issue Other is obviously wait for F# team to implement workspaces properly as first step to hot reload Please leave a message in that issue so it won't be a one man problem |
@vzarytovskii I know that hot reload is considered to be a huge effort, but is there anything the community can do to move things forward? @farlee2121 was able to make (what appears to be) at least a bit of progress. I'm not sure if there have been many conversations on what is required to complete this feature, or if new tasks have come to light. Some questions I have as a (relative) layperson:
I'm really eager to be able to use this feature, especially as it would massively improve some workflows related UI programming (a focus of mine at the moment 😅 ). Thank you! |
I guess any help with figuring out all the components involved in C#'s hot reload will be helpful. Will allow us to frame things better.
Hot reload is coupled with MSBuild, workspaces and project evaluation FWIU. Maybe @baronfel has more context here?
To be able to properly reload running project, we need to either: a. Know how to compile changed piece of code and inject it into running process/patch IL (kind of like what C# does when we evaluating expressions in debugger right now).
I guess the main blocker is that we don't really know/understand the full picture of what's involved in this work. We have bits and pieces.
No, they are not related at all. Transparent compiler is mostly about new compiler/checker pipeline, not really related to codegen. |
I am creating some HTML reports with Giraffe in Visual Studio and just realized hot module reloading wasn't working, which led me here. |
@tmat , Do you happen to have any additional insight on what steps we can take to add hot reload support to F#? |
@NatElkins I think it'd be best to follow the code paths in Roslyn. You can start with the entry-point, which is From there we call Once we know what the changed documents are we diff them and analyze the textual changes to find out which symbols are affected by the change and how. This is rather sophisticated analysis and entirely language specific. See Once the set of semantic changes is determined and if there are no rude edits or other issues The compiler finds the symbols that need to be recompiled and emits them. There is a lot of sophistication here as well that's specific to language syntax, semantics and how each language construct maps to the IL and metadata. When emitting IL and metadata updates it is often desirable (more so for EnC then for Hot Reload) to emit matching metadata names/signatures for compiler-generated metadata entities or emit local variables of updated methods to matching slots. For example, if the code registers a lambda in an event handler and the user updates the body of the lambda we need to update the existing IL method body generated for the lambda, not generate a new one. This is because the delegate created for the original lambda wouldn't know about the new method, so it would keep invoking the original one. Once the compiler produces lowered representation of the changes that have the proper matching signatures, slots, etc. it needs to emit it to the EnC delta metadata format. Here we need to assign tokens to the entities that match the previous metadata entity of the same signature. We also need to keep track of deleted entities (a method can be deleted, added back and deleted again). |
Any plan for this in 2025? Now we got a lot of frameworks for fsharp to develop web UI targeted to dotnet like Falco, Giraffe, Fun.Blazor etc. If the hot-reload can be supported then the dev experience will be at the top layer. The hot-reload is really needed, I think it should be put at the top priority. |
It is a huge pain that putts all this stuff away of F# developers. As without the hot reload developing frontend in F#/.NET is not economically efficient |
➕💯 Note that you can also use vite-plugin-fable to develop web apps with Fable and Vite’s integrated (JavaScript) hot reload system. |
I know fable is there, but a lot of frameworks are targeting to dotnet. |
I do very much envy Fable's compile times when I'm working on server side or desktop stuff. |
Here's a recent presentation from JetBrains' .NET Days that goes over some hot reload internals: https://www.youtube.com/watch?v=MGUPW9sK2Vg |
Is your feature request related to a problem? Please describe.
C# is getting Hot Reload for .NET 6. Will F# receive the same experience? Roslyn has had work done to support this. The F# compiler doesn't seem to have any equivalent work on this.
Describe the solution you'd like
F# can use hot reload just like C#.
Describe alternatives you've considered
Staying behind in terms of tooling again.
Additional context
If the issue is about:
Add any other context or screenshots about the feature request here.
dotnet/core#5510
The text was updated successfully, but these errors were encountered: