The Wayback Machine - https://web.archive.org/web/20220122040730/https://github.com/dotnet/fsharp/issues/11636
Skip to content
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

Open
Happypig375 opened this issue Jun 5, 2021 · 27 comments
Open

Hot Reload #11636

Happypig375 opened this issue Jun 5, 2021 · 27 comments

Comments

@Happypig375
Copy link
Contributor

@Happypig375 Happypig375 commented Jun 5, 2021

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:

  • improving a compiler error message: No.
  • improving/adjusting the parser: No.

Add any other context or screenshots about the feature request here.
dotnet/core#5510

@Happypig375
Copy link
Contributor Author

@Happypig375 Happypig375 commented Jun 5, 2021

https://devblogs.microsoft.com/dotnet/introducing-net-hot-reload/

F# is currently not supported in .NET 6 but we are planning to support in a future release based on customer feedback.

Of course F# is staying behind in terms of tooling again. 😞

@charlesroddie
Copy link
Contributor

@charlesroddie charlesroddie commented Jun 5, 2021

What's the current status if:

  • You run a C# project that supports edit and continue/hot reload
  • This depends on an F# project
  • After making a change in the F# project, you build it.

Is hot reload able to support that currently? I.e. loading the updated assembly.

@cartermp
Copy link
Contributor

@cartermp cartermp commented Jun 5, 2021

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.

@KevinRansom
Copy link
Member

@KevinRansom KevinRansom commented Jun 8, 2021

@happypig, @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.

@forki
Copy link
Contributor

@forki forki commented Jun 9, 2021

@charlesroddie
Copy link
Contributor

@charlesroddie charlesroddie commented Jun 9, 2021

From the linked thread:

dotnet/core#5510 (comment) How fast developers can make code changes and see the resulting impact in their apps is directly proportional to how productive they can be.

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?

@heronbpv
Copy link

@heronbpv heronbpv commented Jun 9, 2021

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 can do it in VS 2015 with the plugin for something like winforms, for example. It's more clunky than have it done automatically, for sure, but also closer to home.

@albertwoo
Copy link

@albertwoo albertwoo commented Jun 24, 2021

I am using blazor with fsharp. Hot reload will speed up the poductivity a lot.

@farlee2121
Copy link

@farlee2121 farlee2121 commented Jul 20, 2021

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 currently have a great feel for the scope of work needed)

@vzarytovskii
Copy link
Member

@vzarytovskii vzarytovskii commented Jul 20, 2021

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 currently have a great feel for the scope of work needed)

I don't think we have a full understanding of what has to be done yet.

@farlee2121
Copy link

@farlee2121 farlee2121 commented Aug 23, 2021

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

  • TODO: Looking into F# partial compilation capabilities
  • TODO: Look into support for solutions with projects in multiple languages
  • TODO: understand where application state is preserved

@farlee2121
Copy link

@farlee2121 farlee2121 commented Sep 1, 2021

A quick update. I made an experimental fork.

It's pretty basic so far

  • Handles project changes
  • Handles new files
    • There is a gotcha with VisualStudio. The build fails because the VS implicitly modifies the project file, but doesn't save it right away
  • Rebuilds on any change to any .fs file

The running program will show changes, and much faster than the existing dotnet watch. The main issue is that debug artifacts are not updated with this strategy.

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.

@NatElkins
Copy link
Contributor

@NatElkins NatElkins commented Sep 2, 2021

@farlee2121 Don't be shy, post a GIF!

@farlee2121
Copy link

@farlee2121 farlee2121 commented Sep 6, 2021

Here's a demonstration of the most basic scenario, changing a file

fsharp-watch

@kerams
Copy link
Contributor

@kerams kerams commented Sep 6, 2021

Sorry for my ignorance, but what exactly is that demonstrating? Watch will recompile and relaunch an application today without hot reload.

@farlee2121
Copy link

@farlee2121 farlee2121 commented Sep 6, 2021

Correct.

Here is the described state of my experiment I was asked to gif.

It's pretty basic so far

  • Handles project changes
  • Handles new files
    • There is a gotcha with VisualStudio. The build fails because the VS implicitly modifies the project file, but doesn't save it right away
  • Rebuilds on any change to any .fs file

I also believe it to be faster, but my sample is only one project.

While the above requirements are met with the DotNetWatcher, they also have to be implemented for F# in HotReloadDotNetWatcher.
You could interpret this gif as demonstrating the most basic F# reloading, but working in the Hot Reload implementation of dotnet watch.

I'm still working on demonstrating updates to F# code using existing delta appliers (true hot reload).

@kerams
Copy link
Contributor

@kerams kerams commented Sep 6, 2021

I see, thank you.

@farlee2121
Copy link

@farlee2121 farlee2121 commented Sep 23, 2021

An update on my efforts.

  • I started some new consulting projects, so my time for this has declined and progress has slowed.
  • I've had to back-fill a lot of knowledge about compiled artifacts (dlls, pdbs)
  • I thought I had figured out the data format needed for live updates applied by IDeltaApplier by digging through the roslyn implementation. However, my test implementation didn't work.

A few other conclusions likely obvious to the FSharp team, but I had to dig for

  • It appears FSharp Compiler Services has the underlying tooling we need to generate incremental updates
  • Incremental updates can be created using FSharpChecker then diffing the compiled outputs, but it seems we could make smarter updates with access to internal-only API methods. Thus, we'll likely want to add hot reload binary patch /delta generation to the compiler services and simply invoke it from the appropriate place in dotnet-watch

Things I'll probably need help on if I can demonstrate a successful reload

  • Project cracking is very confusing, I traced a lineage of several deprecated project crackers, we probably don't want core tooling to depend on the current ionide cracker. How are we supposed to build a project graph?
  • Feedback on where the hot reload delta generation should live in compiler services
  • Understanding live update limitations (rude edits)

@xperiandri
Copy link

@xperiandri xperiandri commented Sep 24, 2021

I suppose @farlee2121 needs someone from Roslyn/HotReload team to join this thread

@farlee2121
Copy link

@farlee2121 farlee2121 commented Sep 24, 2021

That would certainly help

@farlee2121
Copy link

@farlee2121 farlee2121 commented Oct 9, 2021

I got a bit more work in tonight.
Specifically, I traced how the tests were generating deltas, and it comes back to a utility based on the same Roslyn method I was looking at before . The issue is that it passes around a bunch of mutable byte streams and I'm having a hard time tracking with what all happens to those mutable streams.

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 Scope

My 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 FSharpCompilationHandler class.

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 <ProjectCapability Include="SupportsHotReload" /> to the Fsharp targets file

@albertwoo
Copy link

@albertwoo albertwoo commented Dec 10, 2021

Any progress so far?

@farlee2121
Copy link

@farlee2121 farlee2121 commented Dec 18, 2021

I started a new job and haven't had time for this lately.
I'll probably need to reach out to the roslyn team to better understand the delta formats

@albertwoo
Copy link

@albertwoo albertwoo commented Dec 23, 2021

@dsyme can you please help on this cool feature? Do you know any Roslyn team members who can help here?

@PiotrJustyna
Copy link

@PiotrJustyna PiotrJustyna commented Jan 20, 2022

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 👀

@askpt
Copy link

@askpt askpt commented Jan 21, 2022

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.

@albertwoo
Copy link

@albertwoo albertwoo commented Jan 22, 2022

It can improve bolero developments. I am also making a library Fun.Blazor, looking forward to hot reload for a long time. I hope F# team can take this as soon as possible, they and Roslyn team are all in Microsoft right? They can discuss the C# implementation detail.
Hope it will happen soon...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet