|
|
|
|
|
by to11mtm
1637 days ago
|
|
> C# has them. For instance, interfaces used as generic type constraints are zero cost. Depends on what we mean by 'zero cost'. For instance, Interface constraints themselves may not have a 'cost', but there are many cases where this means that the calls involving that generic type will be virtual (unless you're doing fun patterns like 'where TComparer : IEqualityComparer<T>,struct`). If you poke around at the internals of System.Linq you'll see there's a lot of checking to use specialized types depending on the collection in order to minimize costs. And that's what you'll see a lot of in the .NET Standard bits; even in the past we've had some fairly low cost abstractions in places. SocketAsyncEventArgs, if a little arcane at first is a good design for it's time, and System.Linq.Expressions has been a great way for users to minimize the cost of things like reflection without having to write bytecode. That said, some abstractions are deceptively costly; the 'new' generic constraint is definitely not zero cost, unless that got fixed in 6.0. |
|
These fun patterns are precisely generic type constraints I mentioned in my comment. I do use them when performance matters, here’s an open-source example: https://github.com/Const-me/Vrmac/blob/1.2/Vrmac/Draw/Main/I... That code is from a 2D vector graphics library, these interface methods may be called at 10 kHz frequency or more. Displays are often 60 Hz, the methods are called couple times for every vector path being rendered.
> If you poke around at the internals of System.Linq you'll see there's a lot of checking to use specialized types depending on the collection in order to minimize costs.
Linq is awesome, but I’m pretty sure it was designed for usability first, performance second. I tend to avoid Linq (and dynamic memory allocations in general; delegates are using the heap) on performance-critical paths. YMMV but in most of the code I write, these performance-critical paths are taking way under 50% of my code bases.
> 'new' generic constraint is definitely not zero cost
If you mean the overhead of Activator.CreateInstance<T> when generic code calls new() with the generic type, I’m not 100% certain but I think it’s fixed now. According to https://source.dot.net/, that standard library method is marked with [Intrinsic] attribute, the runtime and JIT probably have optimizations for value types.