WhereSequence: improve iteration performance by caching value lookup #1201
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR is significantly improves default iteration performance for
WhereSequence
s by eliminating a redundant call to.iteratorValue
of the underlying sequence. This is relevant in cases of nested calls to.where
like in the following naive implementation of the Sieve of Eratosthenes (see #1200) which have to resolve a lot of references to produce a final result.With unmodified wren 0.4.0, the above takes about a minute to execute on my machine. With the patch from this PR, execution time drops to 3 seconds.
An attempt to explain this insight: The iterator protocol usually means that a call to
iterate()
returns the current iterator value, a sort of "key" that can be used to look up a value using a call toiteratorValue()
. So iterating over a sequence causes alternating calls toiterator()
anditeratorValue()
to be made.In case of the
WhereSequence
however, the.iterator()
method internally already itself calls.iteratorValue()
on the underlying sequence to determine if the filter function matches or not. The value can simply be cached and returned on the next call to theiteratorValue()
method of the envelopingWhereSequence
, rather than patching through to the underlying sequence and callingiteratorValue()
again on that.