- Notifications
You must be signed in to change notification settings - Fork5.1k
Use Iterator<T>.TryGetFirst in Enumerable.Any()#99218
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Conversation
Enumerable.Any() currently uses TryGetNonEnumeratedCount, comparing the result to 0, and TryGetNonEnumeratedCount uses `Iterator<T>.GetCount(onlyIfCheap: true)`. But this leaves out iterators for which it's not cheap to compute the count; for these, however, we can now benefit from every `Iterator<T>` providing a `TryGetFirst`; its `found` result can be used as the result of `Any`. This PR inlines TryGetNonEnumeratedCount into Any and then updates its use of `Iterator<T>` to first use GetCount and then fall back to using TryGetFirst if GetCount is unsuccessful.
ghost commentedMar 4, 2024
Tagging subscribers to this area: @dotnet/area-system-linq Issue DetailsEnumerable.Any() currently uses TryGetNonEnumeratedCount, comparing the result to 0, and TryGetNonEnumeratedCount uses
usingBenchmarkDotNet.Attributes;usingBenchmarkDotNet.Running;BenchmarkSwitcher.FromAssembly(typeof(Tests).Assembly).Run(args);[MemoryDiagnoser(false)][HideColumns("Job","Error","StdDev","Median","RatioSD")]publicpartialclassTests{privateIEnumerable<int>_data;[Params(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19)]publicintSource{get;set;}[GlobalSetup]publicvoidSetup(){IEnumerable<int>data=Source>=10?Iterations(100):Enumerable.Range(0,100).ToArray();_data=(Source%10)switch{0=>data,1=>data.Select(i=>i),2=>data.Where(i=>i%2==0).Select(i=>i),3=>data.Order(),4=>data.OrderBy(i=>i).Select(i=>i),5=>data.Skip(20).Take(10),6=>data.Reverse(),7=>data.SelectMany(i=>newint[]{i}),8=>data.Distinct(),9=>data.Concat(data), _=>thrownewNotSupportedException()};}[Benchmark]publicboolAny()=>_data.Any();privatestaticIEnumerable<int>Iterations(intcount){for(inti=0;i<count;i++)yieldreturni;}}
|
Enumerable.Any() currently uses TryGetNonEnumeratedCount, comparing the result to 0, and TryGetNonEnumeratedCount uses
Iterator<T>.GetCount(onlyIfCheap: true)
. But this leaves out iterators for which it's not cheap to compute the count; for these, however, we can now benefit from everyIterator<T>
providing aTryGetFirst
; itsfound
result can be used as the result ofAny
. This PR inlines TryGetNonEnumeratedCount into Any and then updates its use ofIterator<T>
to first use GetCount and then fall back to using TryGetFirst if GetCount is unsuccessful.