-
-
Notifications
You must be signed in to change notification settings - Fork 137
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
Support GHC JavaScript backend #738
Conversation
js-sources from the `miso.cabal` file are not linked into all.js. One work around for this is to `cp jsbits/*` to the `.jsexe` directory and edit the `index.html` file and add: ``` <script language="javascript" src="delegate.js" defer></script> <script language="javascript" src="diff.js" defer></script> <script language="javascript" src="isomorphic.js" defer></script> <script language="javascript" src="util.js" defer></script> ``` To build one of the examples with the included haskell.nix flake: ``` nix develop .# javascript-unknown-ghcjs-cabal build todo-mvc cp jsbits/* dist-newstyle/build/javascript-ghcjs/ghc-9.8.2/miso-examples-1.8.3.0/x/todo-mvc/build/todo-mvc/todo-mvc.jsexe/ vim dist-newstyle/build/javascript-ghcjs/ghc-9.8.2/miso-examples-1.8.3.0/x/todo-mvc/build/todo-mvc/todo-mvc.jsexe/index.html ```
Considering that the linking would be done in Cabal 3.12, wouldn't it make most sense to just gate the buildability on Cabal 3.12 in the cabal files? |
I can make a cabal pre-release in GHCup, so we can test this. (I have no interest in the nix portion) |
I added cabal prerelease 3.11.0.0.2024.4.19 haskell/ghcup-metadata@eaf801c But I can't build the todo-mvc. There are too many errors with dependency resolution. It has not been kept up to date. |
I forgot to include cabal in the nix develop shell and had 3.9 in my PATH. I've updated that and now the Tested with
|
What are the errors? |
@hamishmack I noticed this uses haskell.nix. Are you aware of any efforts to upstream the GHC derivations (both js backend and wasm backend) into nixpkgs proper (similar to what ghcjs did earlier), utilizing @Ericson2314's existing cross infrastructure? @hsyl20 Since ghcjs-8.10 there seems to have been regressions in the optimization backend (leading to larger payloads), this is why miso stays pinned on ghcjs-8.6. If this PR were to be merged, would the new js backend be at feature parity to ghcjs-8.6 ? Or, is this merge at risk of causing regressions? Current status page seems to indicate the optimizations are still not ported yet from 8.6. I wouldn't mind helping with this endeavor unless its already in flight. @hasufell thanks for building todo-mvc w/ the new js backend, can we capture the build failure log in a new issue |
We haven't ported the Compactor from ghcjs so code size is probably larger with the JS backend than with ghcjs-8.6. So expect regressions regarding code size for now. Performance should be better though (especially TH). We don't have anything in flight about this (JS backend is no longer a priority at work). Nevertheless a new contributor has been working on code size: https://gitlab.haskell.org/ghc/ghc/-/issues/24584 / https://gitlab.haskell.org/ghc/ghc/-/merge_requests/12330 |
Then adding
|
FWIW, Obsidian has also been using Haskell.nix as of late. @sternenseemann has done much more work with GHC packaging in Nixpkgs than me as of late, I would ask him about this. |
@hasufell Are you using head.hackage? They should have a patch for text-short: https://gitlab.haskell.org/ghc/head.hackage/-/blob/master/patches/text-short-0.1.5.patch |
@hsyl20 IIRC the js payload sizes I've seen for ghcjs without the compactor are a full order of magnitude or two too large for production use when compiling larger codebases. I'm assuming this PR should not be merged into master prior to the addition of such a compactor or equivalent. Although it's possible I'm mixing it up with other code size related ghcjs regressions I've seen, will try to test soon to verify. |
TBH I don't think that argument of not merging this until there is a compactor makes sense. As far as I understand it, merging this patch does not prevent you from sticking to an ancient ghcjs, so whatever you are using remains usable. On the other hand, not merging it does make sure that newer people cannot use the new, up to date, ghc js backend with miso, even for small projects where code size does not matter too much [1]. Once we/people can actually build/use the js backend, that may also stimulate contributions to actually improving these aspects of the current js backend. I think that simply waiting even longer will (even further) hamper adaption of the js backend. [1] yes, I know you can again check out this specific PR branch etc. But all of this makes life much more annoying than needed. |
It has been possible to use As for the wasm backend, I concluded last year that it the packaging situation is way to brittle at the moment: NixOS/nixpkgs#225000 (comment). I haven't checked if anything's changed lately. From my perspective the LLVM patches the wasm backend needs would need to be upstreamed and probably the ones for wasi-libc as well. |
Yes that works. But I believe that should be part of this PR then? |
@noinia ah I had assumed it would replace the existing setup, but it looks like it takes advantage of the Getting ghc javascript backend support for end users seems like it doesn't actually require miso to use the new stuff internally though. As long as miso gets the flag changes and gets pushed to hackage/stackage then haskell.nix users are just going to pull it from there anyway and not touch any nix/similar files in the miso repo itself. I'd personally say it makes the most sense to PR just those changes and leave miso's nix config alone until there is high certainty that it is an upgrade for real world ghcjs users to full-switch to the new stuff. |
@sternenseemann thank you for your work on upstreaming the js and wasm backends into nixpkgs proper. These derivations would fit nicely with the existing nix infrastructure in @sternenseemann for this PR ideally we could utilize the cabal file and CPP changes that @hamishmack has provided, along with your nixpkgs work (both js and wasm -- linked above) as well. Regarding the wasm backend, maybe we could all (@dmjio @sternenseemann @TerrorJack) sync over matrix what's required to get your PR updated and into nixpkgs in a way that doesn't feel brittle (since some corporate users are enthusiastic about this work). Per talks with @TerrorJack, it might no longer be necessary to apply additional patches to GHC but it seems we still need to maintain a custom patchset on top of llvm. I'd be willing to help maintain these derivations if they were merged into nixpkgs and perform any necessary changes as they arise from @TerrorJack's development. |
Oof. >14MB binary size for Miso's TodoMVC. This is before closure and any other build size reducing flags (are there any? I've used dedupe and GHCJS_BROWSER in ghcjs-8.6 but I don't think either work with new backend), but still a pretty insane difference vs ghcjs-8.6's 1MB. I'm guessing our currently-10MB much larger work codebase would exceed 100MB, although the effort required to get it building is too high for it to be worth it right now without higher odds of a viable end result. Given the above I stand by the above course of action, namely removing the
|
Thanks for checking this! Could you please open a ticket on GHC's gitlab about this JS code size issue:
I believe that having the old small version as a reference could be motivating for someone to try to do at least as well and to look for differences in the generated code. I also agree with the suggested plan for this repo. |
@hsyl20 It seems this issue is documented here ghcjs/ghcjs#821 (unless this is no longer relevant? and code size is now due to a different issue). Is @luite no longer going to be prioritizing work on the JS backend? I think he might be the best chance to solve this to get us back to @Ericson2314 you mentioned Obsidian is using this new backend w/ haskell.nix, how is the increase in payload size being addressed? @stepcut, curious to know if you've tried the new backend as well. |
@dmjio We've been using |
@dmjio Most of the optimizer mentioned in this ticket has been reimplemented by Luite in the JS backend for 9.10 (I don't remember if it has been backported into 9.8). Iirc some parts of it were unsound in the earlier implementation and that's why it had been disabled in the past and reimplemented from scratch. I would recommend migrating ghcjs issues that are still relevant to the JS backend to GHC's issue tracker: https://gitlab.haskell.org/ghc/ghc/-/issues We've been unsure about what to do with GHCJS issues now that GHCJS is basically discontinued.
Yes Luite is a member of my team and we had to deprioritize the JS backend to work on other things, at least for now. Some of our objectives with the JS backend were to reduce the maintenance cost (bumping GHC versions...) and to allow for new devs to join the effort so that it doesn't fully rest on Luite's shoulders. It's starting to pay off, e.g. Serge has been doing some good work lately and we're assisting him and others as much as we can. I'd recommend opening a ticket about this issue on GHC's gitlab, so that GHC devs (including Luite) can discuss what to do about it and hopefully find someone to execute. If there is a pressing need, maybe we (IOG) can provide commercial support and prioritize the JS backend again, but you should get in touch with @angerman to discuss this. |
Thanks @hamishmack for the PR update @hsyl20 I can add this stuff to gitlab soon yes. Should I make a new issue or add it into https://gitlab.haskell.org/ghc/ghc/-/issues/24584? Obviously I'm not paying for the js backend work so anything you guys do is greatly appreciated, but I will say I'm a tad surprised at the timing for the deprioritization. I realize the sunk cost fallacy is a fallacy for a reason, but spending over a year working hard to get this into ghc only for it to be deemed low prio seemingly one remaining issue/epic away from production readiness is kinda wild. Hopefully as you say other devs will take up the mantle, but i'm assuming every ghcjs-8.6 project/organization out there is going to be sticking with 8.6 for now, as I know sadly we will have to. |
@hsyl20 I tend to agree with @tysonzero here. Despite the fact that most social media / news websites all range in 1MB-10MB (sometimes more) of total js delivered, js payload size is the number one impediment to adoption of this library, and has been for ~6 years (as stated by other developers). We've done as much as we can to reduce the problem by putting most of the critical logic in js, using pre-rendering w/ async loading of js, browser caching, closure compiling, but it is still an impasse in the minds of developers (for some reason, due to prior experience etc.), so any regressions in this direction are difficult to justify. In summary, I agree what @tysonzero has said, go with a merge, but avoid tacit approval until feature parity w/ As an aside, I think a solution could lie in the direction of moving GHC towards a whole program optimization approach w/ a dead code elimination pass, similar to what @csabahruska has done / is doing with the GRIN project.. |
I am happy that the "hamishverse" of libraries is now ported over. Being able to try out the new backend in real-world projects can help foster a sense of "the end being in sight", and also triage what exactly is needed to reach feature/perf/etc. parity with GHCJS again for real-world apps. This is a good way to help avoid things getting deprioritized again/further. I also agree it is very important we squash out these code size regressions --- even having an unmerged branch of GHC (the last GHCJS) with the old unsound algorithms restored might be a useful stepping stone. |
I would create a new issue with the reproducer for TodoMVC. There may be more things to do than for the linked issue (e.g. browser specific optimizations). And for this new one we'll have a concrete size target: the code generated by ghcjs-8.6.
Deprioritization was a bit of a surprise for us too. The roadmap of other products changed and the need for the JS backend declined.
The JS backend already does some aggressive dead code elimination (a bit similar to native with I also have some ideas to change the representation of closures to share more JS code (same entry code for closures). I'll open a ticket about it. |
Adding to this, I've been able to get @dmjio Seeing as the nixpkgs snapshot is obtained from hackage/stackage, would it be possible to make a hackage release of miso with the js backend support? I've got it to build locally with some invasive
|
@dmjio |
@alexfmpe out of curiosity what are the binary sizes involved when doing that? Can any of the examples be built more or less the same way without too much fanfare, it'd be nice to be able to easily monitor those. My current smaller 4k LOC / 55 module application clocks in at ~30MB js size without any gzipping, minification or closure compilation with a recent js backend haskell.nix commit. |
Dunno, never used miso. It was sort of a drive-by for me when fixing other stuff in
Not sure. The executables in |
@alexfmpe I pushed |
js-sources from the
miso.cabal
file are not linked intoall.js
.One work around for this is to
cp jsbits/*
to the.jsexe
directory and edit theindex.html
file and add:To build one of the examples with the included haskell.nix flake: