LINQ's INSANE Improvements in .NET 9
Summary
TLDRThe video highlights the performance improvements in .NET 9's LINQ, which can be up to 1,800 times faster in some use cases compared to previous versions. The presenter demonstrates benchmarks comparing .NET 8 and .NET 9, showing significant speed enhancements and reduced memory allocations for common LINQ methods like Any, All, Count, and First. The optimizations include using spans and consolidating iterators, making LINQ more efficient and competitive with handwritten code. The video also covers how these changes can be applied to existing code bases for better performance. Additionally, a new course on behavioral interviews is mentioned.
Takeaways
- π .NET 9 can be up to 1,800 times faster than previous versions in some cases, thanks to performance improvements in LINQ.
- β‘ Microsoft is focusing on optimizing LINQ to make it much faster, addressing its historical performance issues.
- π’ Some companies avoided using LINQ in the past due to performance concerns, but these improvements make it competitive and sometimes even faster than handwritten code.
- π Common methods like 'Any', 'All', 'Count', 'First', and 'Single' have received significant optimizations in .NET 9, leading to up to five times faster performance with no memory allocations.
- π‘ Microsoftβs optimization involves rewriting key LINQ methods using techniques like spans, which help avoid performance bottlenecks.
- π Benchmark comparisons between .NET 8 and .NET 9 reveal significant speed improvements across various LINQ operations.
- π§ Microsoft's LINQ optimizations include smarter method chaining, consolidating multiple operations into fewer steps to reduce overhead and improve efficiency.
- π‘ The use of interfaces like 'IEnumerable' and optimizations such as removing unnecessary virtual dispatch calls contribute to LINQβs improved performance in .NET 9.
- π Methods like 'Skip' and 'Take' are now consolidated, leading to fewer iterations and better performance when processing collections.
- π Memory allocations for empty collections in LINQ methods are eliminated in .NET 9, making these operations up to 20 times faster.
Q & A
What is the main focus of the video?
-The video focuses on the performance improvements of LINQ in .NET 9, showing how it's up to 1,800 times faster in some use cases compared to previous versions.
Why was LINQ historically considered slow?
-LINQ was historically considered slow due to its inefficiencies, which led some companies to avoid using it because of performance concerns.
What are some of the specific methods discussed that saw performance improvements in .NET 9?
-The methods discussed include Any, All, Count, First, and Single, all of which have seen significant performance improvements, with some running up to five times faster and using zero memory allocation.
What approach did Microsoft take to improve LINQ performance in .NET 9?
-Microsoft optimized LINQ in .NET 9 by rewriting certain internal implementations, using spans, and making smarter decisions like avoiding unnecessary memory allocations and consolidating operations like Skip and Take into fewer iterations.
How does the performance of LINQ in .NET 9 compare to .NET 8?
-In benchmarks, LINQ in .NET 9 outperformed .NET 8 significantly, with up to five times faster execution times and zero memory allocations in many common operations.
What are spans, and how are they used in .NET 9?
-Spans are a memory-efficient feature in .NET that allow for accessing and manipulating data without copying it. In .NET 9, spans are used extensively to optimize LINQ operations by reducing memory allocations and improving performance.
What specific optimization techniques were highlighted for LINQ in .NET 9?
-Some key techniques include optimizing data structures like arrays and lists using spans, consolidating iterators in operations like Skip and Take, and optimizing frequently used methods like Where and Select to reduce overhead.
How has the memory allocation been improved in LINQ methods in .NET 9?
-In .NET 9, memory allocation for many LINQ methods has been reduced to zero, particularly in operations on empty collections, which leads to less garbage collection and better application performance.
What benefits does optimizing LINQ in .NET 9 bring to developers?
-The optimizations in LINQ in .NET 9 make developers more productive by allowing them to use LINQ without worrying about performance penalties. The reduced overhead and improved execution times make LINQ a more viable option for production code.
What other improvements were made to LINQ in .NET 9 according to the video?
-Other improvements include enhanced handling of complex operations like Distinct, Append, Reverse, and DefaultIfEmpty, which are now much faster. Additionally, LINQ now avoids full dataset copies for methods like First and optimizes virtual dispatch calls.
Outlines
π Introduction to .NET 9's Link Performance Boosts
In this video, Nick introduces how .NET 9 improves the performance of Link, making it up to 1,800 times faster in certain cases. He reflects on how Microsoft has prioritized performance optimization for Link, a historically slow feature. Nick recalls experiences from companies where Link was prohibited due to its inefficiency, and he expresses excitement about how these improvements now allow it to compete with, or even surpass, handwritten code. The video will showcase benchmarks comparing .NET 8 and .NET 9, demonstrating the performance gains achieved without changing the code, simply by updating the .NET version.
π Exploring Common Link Methods and Their Performance
Nick dives into common Link methods such as `Any`, `All`, `Count`, `First`, and `Single` and explains their role in typical C# code. He sets up a benchmark to measure the performance difference between .NET 8 and .NET 9. After running the benchmarks, Nick reveals the impressive results, with methods performing up to five times faster and with zero memory allocations in .NET 9. He then shifts focus to understanding how Microsoft achieved these optimizations, highlighting changes made to the underlying implementation, such as the use of `Span` for memory efficiency.
π οΈ Optimizing Lists and Arrays with .NET 9βs Memory Marshalling
Nick delves deeper into the performance enhancements in .NET 9, explaining how lists, which are backed by arrays, benefit from optimizations like the `CollectionsMarshal.AsSpan` method. He demonstrates how .NET 9 takes advantage of arrays' internal structures, allowing developers to extract spans for performance gains. Nick also introduces the dangerous but powerful `Unsafe.As` method, which can be used for low-level operations. These techniques significantly optimize common operations, such as `First`, `Last`, or `Single`, by reducing overhead and memory usage when dealing with arrays and lists.
ποΈ Advanced Benchmarks and Link Chain Optimizations
Nick runs more complex benchmarks involving operations such as `Distinct`, `Append`, and `Select`, showing how .NET 9 reduces execution time by consolidating iterators and optimizing chains of Link methods. He explains that .NET 9 can intelligently merge operations that would normally add overhead, like `Where` and `Select`, into a single iterator. This leads to significant performance improvements when chaining Link methods, making code more efficient without sacrificing readability. The results show reductions in memory allocations and execution times, highlighting how well .NET 9 handles more advanced Link operations.
π‘ Interface Refactoring and Memory Efficiency
Nick elaborates on the behind-the-scenes changes that made these optimizations possible, such as refactoring internal interfaces like `IPartition` and consolidating iterators. He discusses how .NET 9 reduces overhead for methods like `Skip` and `Take` by combining operations that used to create multiple iterators into a single iterator. This refactoring leads to fewer virtual dispatch calls, which boosts overall performance. Nick emphasizes that many Link methods have seen improvements, especially for empty collections, which now avoid memory allocation entirely in .NET 9.
π§ Smarter Link in .NET 9: SequenceEqual and Other Enhancements
Nick showcases further examples of performance enhancements in .NET 9, such as the `SequenceEqual` method, which drastically reduces execution time and memory usage by optimizing how data sets are compared. He highlights improvements to methods like `ToLookup`, which can now operate up to 20 times faster. The use of spans and more efficient algorithms has made Link a much more attractive choice for production code, allowing developers to achieve high performance with less effort. Nick ends by asking viewers if these changes have altered their view on using Link in their own projects.
Mindmap
Keywords
π‘.NET 9
π‘LINQ (Language-Integrated Query)
π‘Benchmarking
π‘Memory Allocation
π‘Span<T>
π‘Unsafe Code
π‘Enumerables
π‘Garbage Collection
π‘Chaining
π‘IEnumerable Optimization
Highlights
Link in .NET 9 can be up to 1,800 times faster in some use cases due to major performance improvements.
Historically, Link had performance issues, and some companies even banned its use due to inefficiency.
The improvements in .NET 9 allow Link to sometimes outperform handwritten code, especially in operations like loops.
Benchmark tests show that common methods like Any, All, Count, First, and Single are significantly faster in .NET 9 compared to .NET 8.
In the benchmarks, results showed up to five times faster execution with zero memory allocation for methods like Any, All, Count, First, and Single.
One of the primary optimizations in .NET 9 is the extensive use of spans, improving memory handling and performance.
Microsoft optimized Link by rewriting methods to leverage spans, arrays, and collection marshalling for better memory management.
The improvements in .NET 9 extend beyond basic methods to complex operations like Select, Reverse, and Distinct, which also see major speed boosts.
By optimizing how Link chains methods together, .NET 9 reduces the overhead caused by multiple wrappers in common operations.
The reverse range method, for example, performs almost twice as fast, and distinct operations also show a massive reduction in time and memory usage.
In .NET 9, optimizations like combining iterators for methods such as Skip and Take reduce the virtual dispatch calls, improving performance.
Link now recognizes patterns in operations like Where and Select, consolidating them into a single iterator, which boosts performance for existing codebases without changes.
New internal refactoring in .NET 9 consolidates interfaces like IPartition into fewer, more efficient structures, improving virtual call efficiency.
Memory allocations have been minimized, with methods like Join, Reverse, and ToLookup experiencing up to 20 times faster execution when working with empty collections.
Developers are encouraged to adopt these performance improvements, as they result in substantial productivity gains without sacrificing performance.
Transcripts
hello everybody I'm Nick and in this
video I'm going to show you how link
inet 9 can be up to 1,800 times faster
in some use cases with some amazing
performance Improvement done by the net
team now if you've been following the
link journ up until now you know that
Microsoft is really focusing on making
link as fast as it can be because it was
historically something pretty slow in
fact I worked in companies where we were
not allowed to use Link at all because
of performance reasons so it's very nice
to see Microsoft actually optimizing
link to a very good degree to the point
where it's really competing or in some
cases surpassing handwritten code with
things like Loops for example in this
video I'm going to show you some of the
most important link performance
improvements in net 9 and I'm also going
to show you how Microsoft did it and if
you have a suspicion on how they did it
leave a comment down below okay so let
me show what I have here I have a net 9
project but it's actually targeting both
net 8 and net 9 and I'm going to running
benchmarks against both net 8 and net 9
and comparing the difference because we
want to see without changing anything
but the net version how faster is our
code now I want to start from this one
the benchmarks 4 because I think that's
an example of something that all of us
are using in some capacity so what we
have here is a list where we create a
range of 1,000 items from 0 to 999 and
then we say to list so we create a list
and then we use the any all count first
or single methods these are extremely
common methods in cop I see them all the
time so what I'm going to do is I'm
going to grab the benchmarks for name
and I'm going to run some benchmarks I'm
going to say Benchmark Runner run and
just see where we stand with performance
with these very simple things that all
they're doing is they're taking the
input and then they're running a check
on it it's very common code in C you see
this all the time so let's go ahead and
run the benchmarks and see what we get
back my configuration will allow me to
run it both in net 8 as a Baseline and
also in net 9 in the same execution now
while this is running and in case you
missed it on do train we're running our
last week of the back to school discount
so until the end of September you can
get 30% off any course with code bts30
and actually today we just released a
brand new course on D train called
Career nailing the behavioral interview
and it's co-authored by two authors ni
centino a principal software engineering
manager in Microsoft and Murphy a
software engineering manager at Yelp the
behavioral interview is something many
people are actually failing interviews
on I know we failed many people because
of the behavioral aspect even though
they were very good technically so it's
a core fundamental part of end developer
and many people are skipping on
preparing it because they think if they
write good code that's all there is to
it now the great thing about this course
is that it's still getting the benefit
of the 30% discount but it only applies
for the firstand view so I'm going to
put a link in the description you can
check it out if it's for you and I can
guarantee you that if you learn learn
everything in that course you will never
fail a behavioral interview again okay
so results are back and let's see what
we have here so as you can see we have a
massive massive improvement from five
times faster five times FAS five times
faster three times faster two and a half
times faster and again five times faster
and zero memory allocation for any of
those methods so we go from 1.1 microc
to around 200 NS for any all count first
single now how is Microsoft doing this
because for me I believe that you should
always know how these optimizations
occur so you can actually use that
knowledge on your own code if you have
the opportunity so if we go over here
and we go on any of those methods let's
go on first because we actually kind of
covered this in the last code cop video
but I want to show you again so if we go
in the net 8 implementation of this
method you're going to see that all
first is doing is is getting the
enumerable and then the predicate and
then we go into the try get first method
and it's doing a few checks and then
it's looping around that enumerable so
you have all of these move next and
current calls because of the enumerator
which in net 9 if we go and which use
the N 9 version as you're going to see
this was completely Rewritten and if we
go into try get first now what we're
doing first if we're checking hey can I
actually get the span yes it's always
spans it's only spans you should know
about that by now so can we try to get
the span out of that inumerable coming
in and how are we doing this well we go
in and we say is it an array if it is
use unsafe. as which by the way deserves
a video of its own it's an amazing very
very dangerous feature but if you know
how to use it it's incredible leave a
comment down below if you want me to
make a video on that and if we can do
that then we get the span out of it if
it is a list then we're using the
collections marshall. aspan method which
by the way you can use too to get a span
out of the list on the way this method
is working is by going in and actually
accessing the internal array that every
list is backed by because if we go into
the lists sorry for all the jumping but
if we go into the list every list is
backed by an array actually and then
list is a wrapper around an array that
knows how to resize it effectively and
then adds a bunch of methods on top of
it and if we can do that then we're
getting the span out and we returning it
with some very very interesting stuff
like the memory Marshall do get array
data reference again a method you can
use as well if you know what you're
doing it's some of my favorite methods
to use and if we can do that then we get
out the span otherwise we return an
empty span basically and we say we could
not find the span so go and fall back to
what you were doing before which if we
go back into the original implementation
if you can find the span then go and
fall back for the slower versions but
for the majority of the use cases what
you're using an array or a list this
will be heavily heavily optimized it's
an amazing feature you don't even know
about and I do think you should know
about because those are improvements you
can actually make on your own code if
you want to now there's plenty more
improved here let's take a look at the
benchmarks one class so what do we have
here we have a bunch of innumerables of
1,000 items and we do a few operations
so for example here we turn it into an
array and we say give me the distinct
values in this array or here we append a
value and we select the value of each
item multiplied by two here we have a
reversal here we have a default if empty
and we have a selection again and a
multiplication we have the two list Skip
and take and we have a union and we have
the first last count element ad and
first methods on any of those anur rules
I'm going to run this Benchmark because
I find it very very interesting let's go
ahead and add this this just shows you
that you can do more complex operations
in link and you'll see how they perform
and it's very clever how Microsoft
actually optimized this to be that fast
they really did a lot of changes behind
the scenes to make this possible because
when you chain methods in link well
you're adding a wrapper on top of a
wrapper on top of a wrapper on top of a
wrapper and you have this chain of
responsibility that this has to happen
first and then this has to happen first
and you add one thing on top of the
other but if link was smarter it would
be able to combine some of those
operations
and consolidate some of those iterators
into fewer jumps from one method to the
other and from one operation to the
other and that's exactly what is
happening here let's wait for this
Benchmark to return and I'm going to
show you how everything works behind the
scenes okay so results are back and
let's see what do we have here so as you
can see distinct first from 39 nond down
to eight no memory the memory aspect of
it is always massive to me because again
less allocations less garbage collection
less pausing on your application but
look at this a pen select last from
3.2 microsc to two nanc like crazy
that's the 1,600 times faster just crazy
reverse range half the time default if
empty select element at 2.8 down to four
three times faster here and again many
times faster here so how is Microsoft
doing this well as described Steven to's
performance improvements inet 9 blog
post which these examples are coming
from by the way this is mostly coming
from consolidating internal interfaces
and removing overhead an example would
be that the a buy method for example
followed by a first will now avoid full
data set copies or sorts before wouldn't
leading to way better performance you
also see a lot of internal interface
refactoring so I don't know if you
remember but there is this interface
called I partition which was actually
used by many enables in net that is not
not used anymore instead these things
now are Consolidated in an iterator
which I don't actually know if we have
access to it doesn't look like we do but
if we go over here let's take a look at
net 9 I don't know if I will find it but
I will try yeah here we go iterator of
type T Source now this is used now as
another feather optimization this
basically leads to fewer checks and
cheaper virtual dispatch calls leading
to again better performance a very
similar story can be seen here with Skip
and take Skip and take before would have
two iterators but now they're
Consolidated they're detected and
Consolidated into one skipping another
call ultimately lincoln. net9 just got
way way way more clever and it's more
self-aware you have methods like two
list or two array knowing what's coming
before and being able to optimize how to
deal with that operation the most common
problem with this was the wear and
select methods which would create two
iterators if dolet 9 now sees where and
select it's going to make one iterator
massive boost to all of your existing
code bases just for updating a net
version there's more improvements over
here things like the any call has a
massive Improvement then we have all
these other methods like chunk distinct
group buy join to look up reverse select
select many skip while take while and
where all of that has been optimized
when it comes to empty collections
before net 9 all of these methods would
allocate some memory in net 9 they don't
allocate any memory and they can be up
to 20 times faster with the two lookup
method for example having a massive
Improvement and in benchmarks 5 uh we
have a method like the sequence equal
where you have two different sequences
as an innumerable we have an array of
these values and then we have a list of
the same values executing this would go
from 26 microc seconds to less than 1
micros around 900 Nan just massive
massive Improvement and they're mostly
done with making link clever rare and
also using span more it seems that
Microsoft is really investing in link
which I really really like and I've
actually started using link more and
more in my production code because it
makes me so so much more productive the
minuscule amount of performance I might
be losing just doesn't matter anymore
but now one from you has your opinion
changed on link and what do you think
about those changes leave a comment down
below and let me know well that's all I
had for you for this video thank you
very much for watching and as always
keep coding
Browse More Related Video
Stop Using FirstOrDefault in .NET! | Code Cop #021
"Stop Using LINQ in .NET!"
Every Single LINQ Extension Method With Examples | .NET & C# Essentials
GUIDs no .NET 9: Novidades que VocΓͺ Precisa Conhecer | #balta
Donβt Use UUIDs/GUIDs in Databases. Use this Instead
They made Python faster with this compiler option
5.0 / 5 (0 votes)