-
Notifications
You must be signed in to change notification settings - Fork 358
List module performance improvements #1027
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
Conversation
Co-Authored-By: Skinney <[email protected]>
Thank you, @harrysarson. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpick - missing spaces around ->
let | ||
res = | ||
if ctr > 500 then | ||
if ctr > 1000 then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
var _List_cons = F2(_List_Cons); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
beware: append
vs (++)
does introduce a difference, IIRC.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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: