-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
A few more chain optimizations #4170
Conversation
while (iter.hasNext) { result = f(result, iter.next()) } | ||
result | ||
@annotation.tailrec | ||
def loop(h: Chain.NonEmpty[A], tail: List[Chain.NonEmpty[A]], acc: B): 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.
by passing the destructured list, we avoid an allocation in the Append
case (which is common since Append is the way we combine two chains).
// of the same code as foldLeft | ||
@annotation.tailrec | ||
def loop(head: Chain.NonEmpty[A], tail: List[Chain.NonEmpty[A]], acc: Long): Int = | ||
if (acc < 0L) 1 // head is nonempty |
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.
If I am not missing something, then if (acc <= 0L) 1
should work as well.
Because we know that the head is not empty, so seems we can skip looking further if acc == 0
is given.
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.
yep. Good call. Updated.
Would there be any benefit to leaving these abstract in |
I ran the benchmarks (and added two). Here are the relevant numbers:
so it looks like the |
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.
Looks really cool, thanks!
AFAIU, implementing all the logic in an abstract class rather than spreading it among descendants may benefit from code locality i.e. it should be less likely that an instruction cache will be reloading while executing a method of the abstract class. Perhaps @johnynek may correct me if I'm wrong about that. |
I really don't know. Of course experiments are the best way to find out but even our current benchmarks might steer us wrong depending on the frequency of Empty, frequency or wrapping and structure of concatenation. |
cc @bplommer
implement foldLeft the same way as length(this was not a benchmark win).