Announcing Elm Optimize Level 2!

Elm is fast.

Can we make it faster?

Turns out, yes! :rocket:

We’ve put together elm-optimize-level-2, which is a CLI tool that adjusts the javascript that Elm generates to make it faster. Once installed, you can just call elm-optimize-level-2 instead of elm-make --optimize.

This speedup should essentially be “free” in that you don’t need to do anything to your code, and your post-minification asset sizes should actually be ever so slightly smaller than before.

Big Note - We’ve tested the code on all of our benchmarks and I’ve verified that things seem to be working as expected on Blissfully (our app is something like ~160k lines-of-code Elm program).

However, beware, elm-optimize-level-2 is adjusting the javascript itself! This project does have the potential to break you Elm project in very un-Elm ways.

But also let us know how it goes!

Science and Speed

There are two sides to this project.

The first is that this is actually a science project to gather data on what JS forms would be beneficial for Elm. It’s a lab where we can try things, collect notes, and verify ideas with actual numbers.

The repo already includes:

The second part of this project is to take the transformations that are the most useful and provide them as a tool you can use now.

The Team

Even though this is under my name on the repo, this has been a joint project with Simon Korzunov! I’m positive this project wouldn’t be nearly as comprehensive without him.

Also, my personal inspiration came from Robin Heggelund Hansen’s article on areas where the Elm Compiler’s output could be improved. Definitely check it out!

What sort of speedup are we talking about?

Good question!

Well, first, there needs to be a bit of a disclaimer.

Your numbers will likely vary depending on a lot of different factors.

You may not see any speedup at all depending on what you’re doing.

However, we do have some very encouraging/exciting results!

Here’s a small sample:

Html

Name Transformtions Browser Ops/Second % Change
create a 4 level nested html tree safari 34,899
create a 4 level nested html tree final safari 39,631 (+14%)
create a 4 level nested html tree firefox 15,909
create a 4 level nested html tree final firefox 22,361 (+41%)
create a 4 level nested html tree chrome 28,959
create a 4 level nested html tree final chrome 72,753 (+151%)

Elm Markdown

Name Transformtions Browser Ops/Second % Change
dillonkearns/elm-markdown safari 2,428
dillonkearns/elm-markdown final safari 3,196 (+32%)
dillonkearns/elm-markdown firefox 1,096
dillonkearns/elm-markdown final firefox 2,194 (+100%)
dillonkearns/elm-markdown chrome 2,489
dillonkearns/elm-markdown final chrome 3,572 (+44%)

Let us know if you try this out!

Happy to answer any questions. Hopefully everything works as intended and I’m not forgetting something :sweat_smile:

(Small note, the npm package was published incorrectly, but it now should be working.)

43 Likes

Neat! A couple of thoughts:

  1. I see a modernizeJS transform in the source code, what JS language level is this targeting specifically? I see the spread operator ... and arrow functions so maybe ES2015?
  2. The transforms are based on TypeScript, why did you choose TS instead of e.g. Babel? Just curious
  3. It’d be cool if you included a transform that makes the Elm output a valid ES2015 module - i.e. replaces attaching the Elm global via the dynamic scope code to just be ES2015 exports

Cheers!

2 Likes

Thanks! :rocket:

  1. We only looked into a few transformations that require “modern” javascript. It basically boiled down to using either Object.assign or the spread operator ... as a substitute for the current record update code, as well as using arrow version of functions. To use either of these the target is basically…uh…just not IE :joy: However there are still questions about benefits for both of those transformations and so we didn’t ship a --modernize flag. The exact target would depend on the specifics of the transformations.

  2. I think Simon knew the typescript API for this? I don’t remember us deliberating much for tools, so don’t really recall.

  3. Interesting, what would be the usecase for that? I think that might be more suited for a different project as this one is about preserving functionality/characteristics of the code, just improving speed or asset size and allowing it to be a drop-in replacement.

1 Like
  1. So far the tool doesn’t use any js new features, thus the js target is exactly the same as today. We are researching an option to upgrade to a modern js but this is WIP.
  2. I had some experience with TS api, plus we use some features from typescript compiler such as symbolication and typechecking, also as far as I know typescript is faster than babel.
  3. I actually tried to make one to run es bundlers like rollup/esbuild but they didn’t give enough benefits to justify the effort. @mfeineis do you have a usecase where es module format would be beneficial?
1 Like

Awesome! Do you have any plans to try to improve the Elm compiler/JS generation process itself with this knowledge?

No plans :smiley:

We’re basically just focused on the research aspect of it as well as providing a tool people can use now.

The key part here is seeing how many projects see a meaningful speedup in their Elm code, so I’m hoping people report back what they find!

2 Likes

Hi,

I’d like to try this out but ran into a few problems… The project I want to try it on has a webpack build, so is compiling the Elm through elm-webpack-loader. This does have an option set a different binary, so I tried substituting elm-optimize-level-2 in place of elm.

The problem is that it trips up on the make instruction when tries to run the equivalent of:

> elm-optimize-level-2 make src/Main.elm

My suggestion is that it might be easier to test this if its command line is compatible with that of the elm command, as it would be easier to drop it in as a substitute either by overriding the Elm binary, or temporarily replacing the system elm command with a symlink to it, when working with non-trivial builds?

7 Likes

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.