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

Implement IList<T> on Enumerable.Cast<T> for IList #97956

Merged
merged 4 commits into from
Feb 23, 2024

Conversation

stephentoub
Copy link
Member

using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;

BenchmarkSwitcher.FromAssembly(typeof(Tests).Assembly).Run(args);

[MemoryDiagnoser(false)]
public class Tests
{
    private List<object> _objects = Enumerable.Range(0, 100).Select(i => (object)i.ToString()).ToList();

    [Benchmark]
    public int Count() => _objects.Cast<string>().Count();

    [Benchmark]
    public bool Contains() => _objects.Cast<string>().Contains("99");

    [Benchmark]
    public int SkipTakeCount() => _objects.Cast<string>().Skip(90).Take(10).Count();

    [Benchmark]
    public string First() => _objects.Cast<string>().First();
    
    [Benchmark]
    public string Last() => _objects.Cast<string>().Last();

    [Benchmark]
    public string[] ToArray() => _objects.Cast<string>().ToArray();
    
    [Benchmark]
    public List<string> ToList() => _objects.Cast<string>().ToList();

    [Benchmark]
    public int[] SelectToArray() => _objects.Cast<string>().Select(s => s.Length).ToArray();
}
Method Toolchain Mean Ratio Allocated Alloc Ratio
Count \main\corerun.exe 743.97 ns 1.00 96 B 1.00
Count \pr\corerun.exe 19.18 ns 0.03 48 B 0.50
Contains \main\corerun.exe 1,377.73 ns 1.00 96 B 1.00
Contains \pr\corerun.exe 288.97 ns 0.21 48 B 0.50
SkipTakeCount \main\corerun.exe 818.13 ns 1.00 208 B 1.00
SkipTakeCount \pr\corerun.exe 58.05 ns 0.07 144 B 0.69
First \main\corerun.exe 46.43 ns 1.00 96 B 1.00
First \pr\corerun.exe 28.70 ns 0.61 48 B 0.50
Last \main\corerun.exe 970.45 ns 1.00 96 B 1.00
Last \pr\corerun.exe 28.38 ns 0.03 48 B 0.50
ToArray \main\corerun.exe 1,485.78 ns 1.00 920 B 1.00
ToArray \pr\corerun.exe 514.07 ns 0.35 872 B 0.95
ToList \main\corerun.exe 1,609.57 ns 1.00 2288 B 1.00
ToList \pr\corerun.exe 505.74 ns 0.31 904 B 0.40
SelectToArray \main\corerun.exe 1,132.01 ns 1.00 576 B 1.00
SelectToArray \pr\corerun.exe 475.36 ns 0.42 528 B 0.92

@stephentoub stephentoub added area-System.Linq tenet-performance Performance related issue labels Feb 5, 2024
@stephentoub stephentoub added this to the 9.0.0 milestone Feb 5, 2024
@ghost
Copy link

ghost commented Feb 5, 2024

Tagging subscribers to this area: @dotnet/area-system-linq
See info in area-owners.md if you want to be subscribed.

Issue Details
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;

BenchmarkSwitcher.FromAssembly(typeof(Tests).Assembly).Run(args);

[MemoryDiagnoser(false)]
public class Tests
{
    private List<object> _objects = Enumerable.Range(0, 100).Select(i => (object)i.ToString()).ToList();

    [Benchmark]
    public int Count() => _objects.Cast<string>().Count();

    [Benchmark]
    public bool Contains() => _objects.Cast<string>().Contains("99");

    [Benchmark]
    public int SkipTakeCount() => _objects.Cast<string>().Skip(90).Take(10).Count();

    [Benchmark]
    public string First() => _objects.Cast<string>().First();
    
    [Benchmark]
    public string Last() => _objects.Cast<string>().Last();

    [Benchmark]
    public string[] ToArray() => _objects.Cast<string>().ToArray();
    
    [Benchmark]
    public List<string> ToList() => _objects.Cast<string>().ToList();

    [Benchmark]
    public int[] SelectToArray() => _objects.Cast<string>().Select(s => s.Length).ToArray();
}
Method Toolchain Mean Ratio Allocated Alloc Ratio
Count \main\corerun.exe 743.97 ns 1.00 96 B 1.00
Count \pr\corerun.exe 19.18 ns 0.03 48 B 0.50
Contains \main\corerun.exe 1,377.73 ns 1.00 96 B 1.00
Contains \pr\corerun.exe 288.97 ns 0.21 48 B 0.50
SkipTakeCount \main\corerun.exe 818.13 ns 1.00 208 B 1.00
SkipTakeCount \pr\corerun.exe 58.05 ns 0.07 144 B 0.69
First \main\corerun.exe 46.43 ns 1.00 96 B 1.00
First \pr\corerun.exe 28.70 ns 0.61 48 B 0.50
Last \main\corerun.exe 970.45 ns 1.00 96 B 1.00
Last \pr\corerun.exe 28.38 ns 0.03 48 B 0.50
ToArray \main\corerun.exe 1,485.78 ns 1.00 920 B 1.00
ToArray \pr\corerun.exe 514.07 ns 0.35 872 B 0.95
ToList \main\corerun.exe 1,609.57 ns 1.00 2288 B 1.00
ToList \pr\corerun.exe 505.74 ns 0.31 904 B 0.40
SelectToArray \main\corerun.exe 1,132.01 ns 1.00 576 B 1.00
SelectToArray \pr\corerun.exe 475.36 ns 0.42 528 B 0.92
Author: stephentoub
Assignees: -
Labels:

area-System.Linq, tenet-performance

Milestone: 9.0.0

@ghost ghost assigned stephentoub Feb 5, 2024
@campersau
Copy link
Contributor

Will this still throw System.InvalidCastException: Unable to cast object of type 'System.String' to type 'System.Int32'.?

Enumerable.Range(0, 100).Select(i => (object)i.ToString()).ToList().Cast<int>().Count()

@stephentoub
Copy link
Member Author

Will this still throw System.InvalidCastException: Unable to cast object of type 'System.String' to type 'System.Int32'.?

Enumerable.Range(0, 100).Select(i => (object)i.ToString()).ToList().Cast<int>().Count()

Not as written. These changes are always a balance with which side effects are actually necessary. Where/why are you relying on Cast.Count evaluating the full input?

@campersau
Copy link
Contributor

Will this still throw System.InvalidCastException: Unable to cast object of type 'System.String' to type 'System.Int32'.?

Enumerable.Range(0, 100).Select(i => (object)i.ToString()).ToList().Cast<int>().Count()

Not as written. These changes are always a balance with which side effects are actually necessary. Where/why are you relying on Cast.Count evaluating the full input?

It was just something I thought about while reviewing the code and wanted to check if the behaviour change was intended / known. I don't think I am relying on the exception and/or Cast.Count evaluating the full input.

@stephentoub stephentoub merged commit 8a9d89b into dotnet:main Feb 23, 2024
109 of 111 checks passed
@stephentoub stephentoub deleted the castlist branch February 23, 2024 20:44
@github-actions github-actions bot locked and limited conversation to collaborators Mar 25, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.Linq tenet-performance Performance related issue
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants