Skip to content
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

Fix collection-optimized paths to be at iteration-time #946

Merged
merged 1 commit into from
Jan 26, 2023

Conversation

atifaziz
Copy link
Member

This PR fixes #943.

It fixes the optimised path in the following operators for when the source is a collection:

  • AssertCount
  • CountDown
  • FallbackIfEmpty
  • PadStart
  • SkipLast
  • TakeLast

All of the above operators have deferred execution semantics, but they were binding to the source collection count when invoked and not when the resulting sequence was iterated. Consequently, if the source collection was updated before iteration, the (cached) count and the resulting sequence would be incorrect.

Tests have been added to avoid regressions in the future.

Some tests were removed because the optimisations they were exercising couldn't be maintained anymore. For example, if AssertCount could determine that the source was a collection and had the right count, then it would return the source reference as-is. Now, the count is asserted when iteration start.

Copy link
Contributor

@viceroypenguin viceroypenguin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only concern I'd have is that in some cases, there is a performance advantage to have in .net6+ by using IEnumerable.TryGetNonEnumeratedCount().

The differences are:

  • TryGetNonEnumeratedCount tests ICollection<>, an internal IIListProvider<>, and ICollection
  • TryGetNonEnumeratedCount does not test IReadOnlyCollection<>

The cases where this difference applies are:

  • IReadOnlyCollection<>
  • Certain IEnumerables returned by System.Linq.Enumerable, which implement IIListProvider<>, but not ICollection<>.

@atifaziz
Copy link
Member Author

atifaziz commented Jan 26, 2023

The only concern I'd have is that in some cases, there is a performance advantage to have in .net6+ by using IEnumerable.TryGetNonEnumeratedCount().

That's an improvement rather than a concern 😉 and happy to take a PR on it, but the focus in this PR was to fix the bug as a priority.

Thanks for the review though and reporting the issue in the first place!

@codecov
Copy link

codecov bot commented Jan 26, 2023

Codecov Report

Merging #946 (f6fde96) into master (5b49471) will increase coverage by 0.04%.
The diff coverage is 97.05%.

❗ Current head f6fde96 differs from pull request most recent head 4910703. Consider uploading reports for the commit 4910703 to get more accurate results

@@            Coverage Diff             @@
##           master     #946      +/-   ##
==========================================
+ Coverage   92.39%   92.44%   +0.04%     
==========================================
  Files         112      113       +1     
  Lines        3434     3453      +19     
  Branches     1021     1025       +4     
==========================================
+ Hits         3173     3192      +19     
+ Misses        199      196       -3     
- Partials       62       65       +3     
Impacted Files Coverage Δ
MoreLinq/SkipLast.cs 100.00% <ø> (ø)
MoreLinq/CollectionLike.cs 80.00% <80.00%> (ø)
MoreLinq/AssertCount.cs 96.29% <100.00%> (-0.14%) ⬇️
MoreLinq/CountDown.cs 90.32% <100.00%> (+0.32%) ⬆️
MoreLinq/CountMethods.cs 100.00% <100.00%> (ø)
MoreLinq/EndsWith.cs 100.00% <100.00%> (ø)
MoreLinq/FallbackIfEmpty.cs 96.22% <100.00%> (+7.54%) ⬆️
MoreLinq/MoreEnumerable.cs 94.11% <100.00%> (ø)
MoreLinq/PadStart.cs 97.91% <100.00%> (+0.13%) ⬆️
MoreLinq/StartsWith.cs 100.00% <100.00%> (ø)
... and 4 more

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

@atifaziz atifaziz merged commit c8004ac into morelinq:master Jan 26, 2023
@atifaziz atifaziz deleted the fix/coll-opts branch January 26, 2023 17:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Some operators incorrectly cache count of a collection source
2 participants