5 ms·
Most of the time, it is not because there were too many slow things to be improved, it is mostly because they are adding more facilities to the runtime, enablin
by eknkc 2y ago
Most of the time, it is not because there were too many slow things to be improved, it is mostly because they are adding more facilities to the runtime, enabling other performance improvements.
For example, the ReadOnlySpan type is a recent addition to the runtime and it will allow faster iterations when used. They simply enabled Linq to use it now.
- EVa5I7bHFq9mnYK 2y agoReadOnlySpan is a breakthrough innovative data structure, consisting of a pointer and a _length, that took Microsoft Corporation two decades to invent. Well, better late than never.
- neonsunset 2y agoother languages do not have special pointers that can point to GC object interiors, be transparently addressed with arithmetics and cooperatively updated by GC without pinning, while also allowing to point to stack and unmanaged memory
- EVa5I7bHFq9mnYK 2y agoI see, thanks. Still, x1000 performance improvement is called a bug fix.
- neonsunset 2y agoI encourage you to read through this section: https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-9/#linq https://devblogs.microsoft.com/dotnet/performance-improvemen... and go through the pull requests that it references. The Nx elements figure is a speedup you would expect if you introduce a shortcut to any algorithm that can bypass doing full iteration, and >100x speed-up is what you would expect from going from interface dispatch per element (even if devirtualized behind a guard) to a bespoke vectorized implementation. Even if you happen to have irrational dislike of .NET, this is still useful learning material and perfectly applies to other languages that expose similar functionality (provided they have sufficiently good type system and generics).
- EVa5I7bHFq9mnYK 2y agoAn algorithm that performs a full iteration where a single lookup is sufficient, is a very bad algorithm. An iterator implementation that introduces 100x overhead is a very bad implementation. C++ has types and generics and pipes and is pretty efficient.
- neonsunset 2y agoC++ is absolutely terrible at this, either UX or performance (or sometimes both), and it's not even close ;)
- int_19h 2y agoBut those pointers were around since .NET 1.0. Not only that, but things like e.g. ArgIterator were also there! Span could have been there too; it was really a matter of design rather than technical capability. I think the main reason why C# didn't have this (and other low-level features like plain function pointers) for so long is because the original vision for .NET was that you'd mix and match different languages in your project as needed. So if you needed that kind of stuff, you'd reach out for managed C++ (and later, C++/CLI), while C# was kept deliberately more high-level. And so once that approach was abandoned, C# needed to catch up to be able to play the "one language that can do it all" role.
- neonsunset 2y ago'ret T's aka byref pointers aka managed references in their current form is a relatively recent addition. I can't seem to find which exact version but if my memory is correct - around .NET 5 or so, before that e.g. Spans had to use a specially annotated field with [ByRefLike] attribute. There wasn't really such a forefront support in both the language and the runtime to enable the user scenarios and even, if limited, ref escape analysis that are possible today. .NET 9 goes further and allows types that hold byrefs to be generic arguments, so you can now handroll your own "true" span-based LINQ-like code as well.
- int_19h 2y agoThe ability to have managed references as fields in types dates all the way back to 1.0. What's new is the ability to define custom ref types in verifiable code, but the runtime itself could always do so on a case by case basis - that is how TypedReference, ArgIterator etc have always worked.
- koyote 2y agoGiven that it took C++ a similar amount of time to invent the string specific string_view I don't think it's as simple as you're making it out. ReadOnlySpan is so powerful because it can be used generically and has implicit conversions that allow you to improve the speed of existing methods without breaking backwards compatibility. It's well designed and that takes thought and time.