List module performance improvements#1027
List module performance improvements#1027robinheghan wants to merge 5 commits intoelm:masterfrom robinheghan:list-improvements
Conversation
Co-Authored-By: Skinney <854889+Skinney@users.noreply.github.com>
|
Thank you, @harrysarson. |
turboMaCk
left a comment
There was a problem hiding this comment.
thanks for looking into this
src/List.elm
Outdated
| reverse (indexedMapHelper 0 f xs []) | ||
|
|
||
|
|
||
| indexedMapHelper : (Int -> a -> b)->Int -> List a -> List b -> List b |
There was a problem hiding this comment.
nitpick - missing spaces around ->
| let | ||
| res = | ||
| if ctr > 500 then | ||
| if ctr > 1000 then |
There was a problem hiding this comment.
I wonder why did you change this magic number but I assume some measurements suggested to do so.
There was a problem hiding this comment.
It’s to match the similar number for take. The number should be as big as possible, without risking that people run into stack overflows. Since take has had the number at 1000 for a long while now, and people don’t complain about stack overflows, it seemed sensible to increase it for foldr as well.
|
|
||
| var _List_append = F2(_List_ap); | ||
|
|
||
| function _List_ap(xs, ys) |
There was a problem hiding this comment.
nitpick - I wonder about naming here. For instance cons uses this convention var _List_cons = F2(_List_Cons); (note same naming but different cases)
Line 16 in 4fbcb15
There was a problem hiding this comment.
_List_Cons is a constructor (the function returns a type). _List_cons is a function, which calls the constructor. You’ll see it defined in the List module as a function.
|
I tried running the test suite (using @jerith666's #1017) for this pull and got: This may be a quirk of the hacks used to run the test suite but I thought it worth flagging in case there is an actual problem here. |
|
|
|
@harrysarson sorry for the miss information! when I use |
|
@turboMaCk I have no confidence that |
|
@harrysarson My first attempt was just to run My guess is that it's this call https://github.com/elm/core/pull/1027/files#diff-99e42729736fe9132da4bba9d117b0e0R182 to Line 7 in c9975bf |
|
I actually know very little about how these things work. I doubt anyone but Evan knows. |
|
Now #1017 has landed, if you re run the CI it should go green. (Best way to re run CI is to open and close this pull request) |
| helper val acc = | ||
| append (f val) acc | ||
| in | ||
| foldr helper [] list |
There was a problem hiding this comment.
@sparksp figured out a faster concatMap:
fasterConcatMap : (a -> List b) -> List a -> List b
fasterConcatMap f =
List.foldr (f >> (++)) []Granted, this doesn't take the JS changes into account, so maybe overall your version is faster, but in current elm/core the above snippet wins the benchmark.
There was a problem hiding this comment.
Luckily this is the same as the proposed concatMap 😄 (f >> (++)) is functionally the same as helper just less expressive.
There was a problem hiding this comment.
beware: append vs (++) does introduce a difference, IIRC.
There was a problem hiding this comment.
The JS changes in this PR makes ++ and List.append equally fast. So if this PR was to be merged, I don't think there would be a difference between these two implementations.
There was a problem hiding this comment.
exactly. The point of this PR is to make the non-obvious performance difference between List.append and (++) to go away which will implicitly improve all the other functions defined in terms of append.
I wonder if you have any idea how @evancz feels about the change @Skinney. It's been a while since this was opened.
There was a problem hiding this comment.
I remember that me and Evan looked through this, but I forget what the conclusion of that meeting was. I don't think he was opposed to any of the changes, though.
This PR improves performance of the following functions:
The improvements range from 20% to 100% depending on the browser and function.
More specifically, this is what has been done: