Тёмный
No video :(

C# LINQ Performance Tips #1 - Let keyword & Custom Lookup 

LevelUp
Подписаться 6 тыс.
Просмотров 29 тыс.
50% 1

Опубликовано:

 

22 авг 2024

Поделиться:

Ссылка:

Скачать:

Готовим ссылку...

Добавить в:

Мой плейлист
Посмотреть позже
Комментарии : 59   
@edwardevlogiev4087
@edwardevlogiev4087 4 года назад
Hey, thumbs up for all the effort. I would like to point out that LINQ is designed for readability, not performance, and it's excellent in situations where you need to apply complex transformations over not very big collections. Optimizing where optimizations are not need is, in the best case, harmless.
@LevelUppp
@LevelUppp 4 года назад
True, although one can have it's cake and eaten with LINQ by improving some of the operators by using structs, value delegates, de virtualisation, better branching code etc. My next couple of videos in the series show how to achieve this with LINQ, plus there are frameworks that do this out of the box as well: ♦ github.com/NetFabric/NetFabric.Hyperlinq ♦ github.com/reegeek/StructLinq
@edwardevlogiev4087
@edwardevlogiev4087 4 года назад
@@LevelUppp Yup, certainly and there's nothing wrong with that. My argument is mostly aimed at beginners when they fall into the trap of feeling they MUST optimize or they are doing it wrong.
@johnfrian
@johnfrian 4 года назад
Honestly, the best LINQ performance tip is to not use LINQ. In many cases it's a compromise between readability vs performance, choosing between LINQ and a custom loop that does exactly what you need. There are, of course, cases where LINQ provides nice additions (e.g. null-checks) without doing anything too crazy on top of that (like .Any()). Just be mindful when using methods like GroupBy() which can be up to 9 times slower than a simple foreach.
@LevelUppp
@LevelUppp 4 года назад
Watch the other videos :) you can have your cake an eat it too. It requires some work but you can get LINQ at zero cost, but not out of the box you have to improve and re-implement methods and operators.
@David-id6jw
@David-id6jw 4 года назад
Filter_ToLower_04 has another difference from the first three: It doesn't return the result. So it doesn't have to copy the reference back to/off the stack, which means less memory access, etc. I'm pretty sure that's why it's faster than version 03, and not because of the change in comparison order. Though you're still correct that the number of comparisons in the respective lists will have an impact on a more elaborate app.
@LevelUppp
@LevelUppp 4 года назад
While pushing and pooping the stack does have an impact, it's incredibly fast, in this specific case it was the branch order since the data is skewed in such a way that the branch order does make an impact. That missing return was an accidental omission on my part and I've fixed it later.
@danflemming3553
@danflemming3553 4 года назад
At 11:50 where you talk about LINQ's Last() method, you say that LINQ doesn't check to see if the enumerable is actually a list. That's incorrect. LINQ does that actually: github.com/microsoft/referencesource/blob/master/System.Core/System/Linq/Enumerable.cs#L1091 And in the next line, you can see it actually calls the index: if (count > 0) return list[count - 1]; github.com/microsoft/referencesource/blob/master/System.Core/System/Linq/Enumerable.cs#L1093 More importantly, your code works faster also because you don't check like LINQ to see if the list has any elements in it before accessing the index. This isn't the main cause why your code is faster, but it's important to note. The performance penalties you're seeing are of different reasons, not because LINQ doesn't check if the instance is a list
@LevelUppp
@LevelUppp 4 года назад
Yeah the old version of LINQ didn't do that check. The new version indeed does the check. The type check is what's slowing it down, and since it's using the interface version all calls are considered VCalls and it's another tiny penalty that is relevant at scale. Thanks ❤️
@danflemming3553
@danflemming3553 4 года назад
Don't get me wrong, your content is OK, LINQ is slower but some of the reasons you say why LINQ is slower not all of them are correct. Keep up the good work and thanks
@LevelUppp
@LevelUppp 4 года назад
@@danflemming3553 Hey, I'm not bothered or anything like that. I think you're doing great work correcting all of the mistakes that I've made. This will lead to better quality videos, more discussion, small arguments, corrections and everyone will benefit at the end. Thanks :)
@danflemming3553
@danflemming3553 4 года назад
@@LevelUppp Wow, great attitude dude 👍🏻 Many don't understand that and would be offended! It's exactly my point, the idea is to improve, we all need to learn and improve. I have a lot of things I need to improve myself and your videos are great!
@danflemming3553
@danflemming3553 4 года назад
@@LevelUppp Actually Last() works like that at least since 2014, that's at least 6 years ago 🙂: github.com/microsoft/referencesource/blob/9da503f9ef21e8d1f2905c78d4e3e5cbb3d6f85a/System.Core/System/Linq/Enumerable.cs#L967
@JacekGasiorowski
@JacekGasiorowski 4 года назад
Hello, I might be wrong but your example with GroupBy_O1 might be totally incorrect. By using your group by LINQ query you only building expression tree which is not materialised anywhere (you are not calling .ToList() after query or just .Count()) so your mesurement only shows how long it takes to build the LINQ expression for the runtime. I is never executed. I tried that example myself and with .ToList() call it takes almost 9 times more time than withou it. I think it might be a mistake on your side because you used .ToList() call in examples with filtering
@LevelUppp
@LevelUppp 4 года назад
You're right, thanks!
@LevelUppp
@LevelUppp 4 года назад
I'll correct that in another video
@LevelUppp
@LevelUppp 4 года назад
And here I was thinking that there's a saving grace for LINQ but no :( although it's sill not that bad in performance numbers but my Lookup absolutely destroys LINQ.
@JacekGasiorowski
@JacekGasiorowski 4 года назад
@@LevelUppp Exactly :) good job :)
@LevelUppp
@LevelUppp 4 года назад
@@JacekGasiorowski No that makes me sad since I wanted to love the built in Lookup ;-(
@Bjarkediedrage
@Bjarkediedrage 4 года назад
When trying to do ECS in c# some time ago, I hit a wall when trying to provide a nice way of enumerating quickly throught various data buckets in an easy way. Mainly because C# can't inline lambdas. (Yet??). For instance: void IterateOnDataBuckets_Slow(Action iterator) { for (...) { // Imagine a more complex iterator. iterator(someData[i]); } } interface DataBucketIterator { void Evaluate(ref Data data); } void IterateOnDataBuckets_SillSlow(DataBucketIterator iterator) { for (...) { // Imagine a more complex iterator. iterator.Evaluate(ref someData[i]); // still quite slow. } } void IterateOnDataBuckets_FastAndInlineable(T iterator) where T : DataBucketIterator { for (...) { // Imagine a more complex iterator. iterator.Evaluate(someData[i]); // Since it's know what T is, it's able to inline this function. } } But of course, having to write a type just to enumearte the data, so I stopped the ECS experiement there. Wondering if you have any experience with that sort of problem?
@LevelUppp
@LevelUppp 4 года назад
Lambdas that need to capture context usually cannot be inlined since the compiler will create a class and push all of the captured variables there, thus inlining is out of the question. This is a current limitation of the compiler since in a lot of cases such treatment shouldn't be needed. Then there's a general problem that delegates cannot be inlined at the calle site yet another limitation that could be improved. What I would do is a struct that describes the iterator this can be created with an lambda function but it returns a struct that describes what needs to be done, this would let you solve the problem, the matching engine would be a bit more complicated (and perhaps limited) but you would see performance gains.
@LevelUppp
@LevelUppp 4 года назад
If you need to iterate quickly you should pay the most attention to the data layout of your components, inlining while help should not be the primary cost. Are you using SOA for components? Have you tried doing SOA with SIMD? For well crafted components and systems using the SOA over SIMD is usually very fast.
@LevelUppp
@LevelUppp 4 года назад
Sorry one last question :) What C# compiler are you using? If it's the Unity compiler things are a bit different there, and if it's the Burst Compiler thins are even more extreme and with the C#9 on the horizon you could try using function pointers but the Unity toolchain is even faster when using SIMD.
@Bjarkediedrage
@Bjarkediedrage 4 года назад
@@LevelUppp It was mostly an experiment to see how close I could get to c/c++ performance. I've not tried and use SIMD before really, but I've been wanting to since seeing your videos.
@Bjarkediedrage
@Bjarkediedrage 4 года назад
@@LevelUppp Yeah, it's really cool how fast they've gotten things with burst. They also inline the delegates, (but I have had some bugs with scope and capturing variables^^). Okay, I was not aware of C# 9 function pointers, that is awesome!
@therealxunil2
@therealxunil2 4 года назад
I would emphasize the point that if you're examining millions of records, those 5ms in your test case will add up to a significant savings in time.
@LevelUppp
@LevelUppp 4 года назад
The problem with that is that if you're around ~5% better it would be good to do a statisticalsignificance test to be sure that your gains are not just random noise.
@psychotrout
@psychotrout 4 года назад
LINQ query syntax is very ugly to read, the method chain version is much more readable and modern in my opinion: transactions.Where(x => ...).Selec(x => x...);
@LevelUppp
@LevelUppp 3 года назад
Yeah I agree.
@theincredibleillmo9385
@theincredibleillmo9385 4 года назад
Great tips, just be aware about coughing all the time, it is really annoying when someone uses headphones.
@Cerstani
@Cerstani 3 года назад
If you thought that was annoying, you should NEVER subject yourself to a DarkSydePhil (DSPGaming) video..
@omarbousbia6916
@omarbousbia6916 4 года назад
Great tips,,, thank you
@sanjayi6245
@sanjayi6245 4 года назад
Very good video.
@LevelUppp
@LevelUppp 4 года назад
Thanks! :)
@sanjayi6245
@sanjayi6245 4 года назад
@@LevelUppp Can you tell me what font you are using in Visual Studio.
@LevelUppp
@LevelUppp 4 года назад
@@sanjayi6245 It's consolas, I've got it by default.
@sanjayi6245
@sanjayi6245 4 года назад
@@LevelUppp Ah. Okay. Anyway continue what you are doing. Cheers
@frankroos1167
@frankroos1167 3 года назад
For the ToLower bit: I am missing the option of first uniting the collections to be filtered by into a single one. That should also limit the number of ToLower calls to 1.
@atmanirbharbharat
@atmanirbharbharat 2 года назад
i there any wy to replacement of .contains. for large DB performance issue
@user-vi7xn1tj9f
@user-vi7xn1tj9f 3 месяца назад
Great video. I would only recommend to work on a proper naming convention, as you named all of the tested methods with quite generic (nothing saying) names.
@abdelrhmanahmed1378
@abdelrhmanahmed1378 2 года назад
in groupByLookup you dont deal with collisions,and when i see the imp of groupBy provided by Microsoft it look very similar to yours , so why the performance gap is hug ?!
@nvtmjfan
@nvtmjfan 2 года назад
What is diff between method 3 and 4.
@ProfessorCodemunkie
@ProfessorCodemunkie 4 года назад
With the let example I wonder what the performance would be like using LINQ method syntax i.e. transactions.Where(t => { var nameLowerCase = t.Name.ToLower(); if.... }).Select(...
@LevelUppp
@LevelUppp 4 года назад
Not sure we can check :) but I assume it would be faster?
@CHITRANSHSHARMA
@CHITRANSHSHARMA 4 года назад
I am 639th subscriber
@m057d0p3
@m057d0p3 4 года назад
Why dont you use BenchmarkDotnet to measure?
@LevelUppp
@LevelUppp 4 года назад
Too slow to measure. It takes an average of ~1-5 minutes per run. However new videos include Benchmark.NET as well either by having it already pre-computed or by speeding up the video 15x times when the benchmark runs.
@jfaquinojr
@jfaquinojr 4 года назад
Anybody else cringe when he coughs? Hope OP is ok
@LevelUppp
@LevelUppp 4 года назад
Had a Flu when I was recording this, sorry :)
Далее
C# LINQ Performance Tips #2 - Structs vs Classes
24:36
Просмотров 4,9 тыс.
5 (Extreme) Performance Tips in C#
12:26
Просмотров 74 тыс.
LINQ in C# - Top 10 concepts everyone should know 🔥
17:54
The weirdest way to loop in C# is also the fastest
12:55
Difference between Select and SelectMany in LINQ in C#
7:14
The Fastest Way to Modify a List in C# | Coding Demo
10:30
Make Your LINQ Up to 10x Faster!
11:08
Просмотров 55 тыс.
AVOID these 3 COMMON C# Performance MISTAKES
14:20
Просмотров 9 тыс.