-
Notifications
You must be signed in to change notification settings - Fork 16
Simplify identity proposal #36
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
base: master
Are you sure you want to change the base?
Conversation
Hi @mdgriffith , what do you think about this optimization? Maybe it was unclear from my initial PR without message, I just would like to talk about this before going through implementation. |
I wonder if minifiers don't already do this transformation? |
Hey! Sorry, I missed the initial notification for this PR. Interesting, yeah I think it could be cool to explore. First thing would be to see if it has an effect or if minifiers or even v8 are smart enough to fix the situation automatically. I'd recommend putting together an elm-benchmark and adjusting the js by hand to see if you can see a benefit. Maybe try it before and after a minifier too so we have an idea if that changes it. If you have those results, we can add them to the description you've submitted here. This project is not only a transformer, but also a place to aggregate knowledge like this. That can inform if it makes sense to do an implementation. Thanks for the write up! |
Yeah, will try to do that. @mdgriffith do you have any example of elm-benchmark running modified JS? |
Hm, so I was thinking on this a little bit. Here are the questions that I think about:
So to test these we probably don't even need to modify the JS. I'd just set up a benchmark like the following: module Main exposing ( main )
import Benchmark exposing (Benchmark)
import Benchmark.Runner exposing (BenchmarkProgram, program)
type Wrapper = Wrapper Int
toInt : Wrapper -> Int
toInt (Wrapper i) = i
range =
List.range 0 1000
wrapped =
range
|> List.map Wrapper
bench : Benchmark
bench =
Benchmark.describe "List.map unwrap"
[ Benchmark.benchmark "elm" (\_ -> List.map toInt wrapped |> List.sum)
, Benchmark.benchmark "without wrapper" (\_ -> range |> List.sum)
]
main : BenchmarkProgram
main =
program <|
Benchmark.describe "Unwrapping overhead"
[ bench
] Then I'd compile with I'm also curious about
|
I've run the benchmark you've proposed, and neither Terser nor V8 perform this "identity simplification" (V8 is even a bit less performant than FF with the wrapped one). Minifier doesn't seem to change anything. I paste my results here for the reccord Non minified
(I suspect V8 to recognize the sum as a special built-in function) Minified
|
I often use this opaque type technique to have some kind of guarantees on the value I manipulate (like wrapping a string for an email). This is also probably used in some computation intensive games -- or maybe people don't use that because of this performance penalty. I'll ask in the gamedev & webgl channels.
Yeah, I'm a bit worried about this as well. Maybe we could get have a useful but not optimal transformation only looking at |
Interesting answer from Ian MacKenzie:
|
Interesting! That's great to know. Yeah, it's a little tricky because if Ian or Andrey or someone starts counting on this optimization and uses it significantly, then it's likely that that will lower performance for people who don't use Ignoring that for the moment, it seems there are probably three situations of interest:
|
I think this technique is very common because the elm compiler already promises half of the optimisation: it removes the runtime overhead of the type wrapper, it just doesn't inline what remains. So in some sense having a general inliner pass would help with this - but I guess with asset size being so important for web apps aggressive inlining is a tricky technique to get right. |
Thoughts about this transformation: doing this in the JS compiled code seems a bit complicated. @mdgriffith What would you think about "pretransform" the elm code before passing it to the compiler? My idea is to transform:
into
replace all the "wrap/unwrap" functions with Overall the process would be:
|
No description provided.