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

Performance: Make constructor List<T>(IEnumerable<T> collection) know about IReadOnlyCollection #27517

Closed
dnickless opened this issue Oct 2, 2018 · 3 comments
Milestone

Comments

@dnickless
Copy link
Contributor

In the following List<T> constructor:

https://github.com/dotnet/corefx/blob/e043326e204a9566ee26403b522cf95cda2d54ee/src/Common/src/CoreLib/System/Collections/Generic/List.cs#L67

there is some special logic built-in already to support the efficient initialization of a List<T> based on an existing ICollection<T>. With the advent of IReadOnlyCollection<T> this constructor logic could be extended to also support this type.

IReadOnlyCollection<T> does not support a CopyTo() method at this stage but at least the cost of array resizes could be alleviated here at the expense of another branch/type check.

@Wraith2
Copy link
Contributor

Wraith2 commented Oct 2, 2018

This will cause a performance degradation in existing code, the majority will pay the cost for something they are unlikely to use and have no opportunity to opt out of it. Casting is relatively slow and generic casts are slower still and can cause jit-ing of the IReadonlyCollection type if it isn't used already.

Adding code to core parts of the clr like Dictionary and List has a multiplicative cost in size because of native copies of common types are precompiled for performance. While that doesn't mean common methods can't increase in size it makes the bar for change approval on high-use types is higher than you'd expect and that evidence of improvement must be considerable.

In this case you could provide an Extension method to create a list from a readonly collection that presizes using the existing api couldn't you?

@stephentoub
Copy link
Member

@dnickless
Copy link
Contributor Author

Well, that is not exactly unexpected...

I just keep coming across this on a fairly regular basis... It popped up in a trace again today - in fact, it wasn't even that List<T> constructor call directly, it was rather LINQ's .ToList<T> in with a parameter of type Dictionary<K, V>.KeyCollection (which implements IReadOnlyCollection<T> only). So initially, I thought of suggesting this change for LINQ's ToList<T> but this already does some magic using the ListProvider interface... It feels a bit like we have a lot of not entirely consistent approaches here.

This IReadOnlyCollection<T> is just one of those less obvious buggers that give you unfortunate surprises because one collection behaves in one way and another one in a different way.

And while I do think that it's unfortunate, that e.g. ICollection<T> does not inherit from IReadOnlyCollection<T> I also think we've covered this elsewhere and there are good reasons so I'll close this one.

@msftgits msftgits transferred this issue from dotnet/corefx Jan 31, 2020
@msftgits msftgits added this to the 3.0 milestone Jan 31, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Dec 15, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants