I Lied! The Fastest C# Loop Is Even Weirder

Поділитися
Вставка
  • Опубліковано 2 кві 2023
  • Check out my courses: dometrain.com
    Become a Patreon and get source code access: / nickchapsas
    Hello everybody I'm Nick, and in this video, I will show you an even weirder way to loop in C#, which in some cases can perform better than every other approach.
    Workshops: bit.ly/nickworkshops
    Don't forget to comment, like and subscribe :)
    Social Media:
    Follow me on GitHub: bit.ly/ChapsasGitHub
    Follow me on Twitter: bit.ly/ChapsasTwitter
    Connect on LinkedIn: bit.ly/ChapsasLinkedIn
    Keep coding merch: keepcoding.shop
    #csharp #dotnet

КОМЕНТАРІ • 96

  • @jackkendall6420
    @jackkendall6420 Рік тому +224

    when you forget to add the # to your C

    • @mad_t
      @mad_t Рік тому +15

      yeah that's definitely c prime way of iterating :)
      In real world though the actual logic inside the loop takes so much more time and resources than iteration then this optimization is completely unnecessary.

    • @SharunKumar
      @SharunKumar Рік тому +1

      BluntC

  • @MechMK1
    @MechMK1 Рік тому +56

    Ah yes, the fastest way to write C# is to write it as if it was C.

    • @desertfish74
      @desertfish74 Рік тому +2

      The fastest way to write code is to actually write C anyway....

    • @manuelamstutz4468
      @manuelamstutz4468 Рік тому +11

      ​@@desertfish74 Not the fastest way to write code.. but a way to write the fastest code :-). Write c takes often longer

    • @desertfish74
      @desertfish74 Рік тому +1

      @@manuelamstutz4468 true haha

  • @MagicNumberArg
    @MagicNumberArg Рік тому +31

    "Hello everyone, this is Nick Chapsas and today I will show you a trick which makes your loop allocate NEGATIVE 128 bytes per item, thats right, LESS than 0, and also makes code in other processes on the same machine run 20% faster! "

    • @phizc
      @phizc Рік тому

      @First Last the Java video was quite good as it was 😄

  • @Eric-kx7do
    @Eric-kx7do Рік тому +14

    I rewrote a legacy C application in C# that was sensitive to performance. I had to use Marshalling to access a legacy C DLL that I couldn’t update but stayed with Spans for the performance increase. In the end the company got a faster, working high performance application that thanks to C# was smaller and much easier to maintain. Your video today convinces me that my choices back then were still correct.

  • @ristopaasivirta9770
    @ristopaasivirta9770 Рік тому +13

    That feeling when you start to get segfault errors in a managed language.

  • @prman9984
    @prman9984 Рік тому +10

    The final AsSpan is the best by far. It's very clear what's happening and extremely close to the unsafe version.

  • @tosunabi1664
    @tosunabi1664 Рік тому +7

    Span is the way to go. Cleaner.

  • @AAAnatoly
    @AAAnatoly Рік тому +10

    A couple of videos later: hello, i,m Nick, and today we will run c++ code in our c# project to iterate array extremely fast))

    • @nickchapsas
      @nickchapsas  Рік тому +16

      Has my video backlog leaked or something?

    • @phizc
      @phizc Рік тому +1

      Actually, that's slower since there's no way of inlining the c++ code, and calling into native, and back to C#, is also wasting performance. It's definitely possible though.

  • @arztje
    @arztje Рік тому +13

    I am definitely using spans a lot more after watching your performance videos. It has helped quite a lot when iterating massive collections.

  • @tanglesites
    @tanglesites Рік тому +16

    Shouldn't you be able to do something similar with pointers? This seems similar to how you can loop in C++ with pointers. Awesome video. I like that C# does not shut you out of the language but gives you a secret door to the goodies.

    • @nickchapsas
      @nickchapsas  Рік тому +19

      You can actually use straight pointers like in C by enabling unsafe compilation. I’ll probably show that in a future video

    • @dryadxon
      @dryadxon Рік тому +9

      In fact it's the same thing under the hood, what it's doing is getting two pointers, one to the first element, the other to the last + 1 element, iterating until the pointers are equal. It is quite common to iterate in this way in C, especially on strings, and although in csharp doing this thing is more difficult and less readable, it is fascinating to find out that it is possible.

    • @chipcode5538
      @chipcode5538 Рік тому +1

      Good old pointer math is back again.

  • @aurinator
    @aurinator Рік тому +13

    While I like your data that shows it's the fastest, its Standard Deviation is high implying something is causing it to occasionally take much longer than the average. I'm wondering what might cause that now.

  • @ali_randomNumberHere
    @ali_randomNumberHere Рік тому +2

    this man just cant leave the loops alone

  • @Kazdro009
    @Kazdro009 Рік тому +13

    If I were to write code for game (especially mobile one) I would seriously consider it. It might be only few ns's but if something is executed N hundred times per second it might improve performance in observable way. Also StdDev for FasterLoop is something worth to consider here in mentioned scenarios.

    • @dire_prism
      @dire_prism Рік тому +3

      Even for games - these kinds of optimizations can always be added at a later stage after profiling your code and determining t's actually spending a lot of time here.
      9/10 times you will actually be doing something inside the loop that will totally overshadow the time spent looping.
      What can't easily be added later is having proper datastructures for the problem. These are definitely worth getting right at earlier stages.

  • @harald4game
    @harald4game Рік тому +2

    Love it. C pointer loops are back.
    I'm not doing time critical c# nowadays but if I had to write a image processing library that would be great option to avoid cross language issues especially for cross platform programming.

  • @Innovatorsoft
    @Innovatorsoft Рік тому

    I really appreciate the advice. I am looking more than video.
    Thanks

  • @rasimismatulin1400
    @rasimismatulin1400 Рік тому +9

    In next video: "I Lied! C# Loop that iterates 10.000.000 items in 0.05 nanoseconds"

    • @nickchapsas
      @nickchapsas  Рік тому +3

      Accurate

    • @metaltyphoon
      @metaltyphoon Рік тому +2

      U can probably do that using SIMD 🤣

    • @phizc
      @phizc Рік тому +1

      @@metaltyphoon nah, not even with simd.. 0.05ns for even 1 instruction requires a 20GHz processor. Maybe in a few processor generations. 😁

  • @patrickcandlin7420
    @patrickcandlin7420 Рік тому

    Love your stuff Nick! Thank you!

  • @sebastiangudino9377
    @sebastiangudino9377 Рік тому +1

    That looks a LOOOOOOT like iterators in C++. Where you take the .begin() and the .end() and keep increasing begin while it is less than end

  • @AndrewJonkers
    @AndrewJonkers Рік тому

    Nice, and good guidance for compiler/GC/runtime future optimisations: we return to the recreating simple optimal assembly/machine code in C# by use of odd obscure keywords.

  • @jongeduard
    @jongeduard Рік тому +1

    Hi! I reproduced your tests on my system and I am getting results close to you, but I also decided to add an actual unsafe method in wich I am using real raw pointer syntax and the required fixed statement to pin the array. Performance of this is very close to your fastest loop, but not faster. In other tests that I did I always discoverd that real unsafe code was still the fastest, so that's a bit of a surprise to me.
    I also want to point out that there is a tiny difference between storing the Length value in a local variable inside your method first and use that variable in your loop instead of directly using the field repeatedly. This is because accessing locals in the stack is still a bit faster than accessing fields from the managed heap.

  • @charlesmayberry2825
    @charlesmayberry2825 Рік тому

    Oh boy, you're starting to get into the territory of how we handle collections in C++, toeing a dangerous line there lol

  • @chadsquad5050
    @chadsquad5050 Рік тому +4

    the "fast loop" using Unsafe.Add with index will be as fast as the "faster loop" if you use nint i instead of int i.

  • @matthewsheeran
    @matthewsheeran Рік тому +2

    The StdDev was almost twice on the FasterLoop so it's results are a little more iffy.

  • @billy65bob
    @billy65bob Рік тому +8

    Looping like we're C++ now. lol.

    • @AcidNeko
      @AcidNeko Рік тому

      Yeah, you can loop that way in C++, but I think performance would mostly the same as ranged for due to cost free abstraction and compiler optimizations

    • @nothingisreal6345
      @nothingisreal6345 Рік тому

      True. I wonder how this would work with goody ol' C# pointers.

    • @billy65bob
      @billy65bob Рік тому

      ​@@AcidNeko the range stuff is just an abstraction for looping with the begin() and end() functions, which are inlined to loop with the start/end pointers in the exact way Nick did here.
      Hence my comment.

  • @DeadlyAlive...
    @DeadlyAlive... Рік тому +1

    I work with Kotlin for the most part and I have almost no experience with C#, I still find those videos very interesting to watch. Thank you!

  • @lifeisgameplayit
    @lifeisgameplayit Рік тому

    Epic ! I thank you Nick ! Blessings from Polska

  • @damkillerxxwin1462
    @damkillerxxwin1462 9 місяців тому

    7:44 what is this fancy debugger it is only exclusive on this IDE? or you can have it on visual studio code or vs?

  • @boxacuva
    @boxacuva Рік тому

    The cylce as completed for long time we went away from pointers and now they are coming back.

  • @nofella
    @nofella Рік тому

    The disasm you're looking at is not the most optimized one due to tiered JIT. The method will definitely be inlined, but that's not really a problem. It's also worth noting that iterating over the array's span instead of the array is only faster because the JIT optimizes the looping over the span better (which IMHO is a bug). Also, this "even weirder" approach was already commented to the original video ;)

  • @djenning90
    @djenning90 Рік тому

    I know about spans but I haven’t started using them. I need to try some experiments in my codebase. What are sone good common use cases to explore?.

  • @georjj
    @georjj Рік тому +1

    Why then is it not default implementation, are there any downsides?

  • @FilipCordas
    @FilipCordas Рік тому +1

    Would stackalloc make a difference in performance?

  • @deltaphilip8611
    @deltaphilip8611 Рік тому

    Reading the code a year from now, will be a "What the hell?" moment.

  • @rick2591
    @rick2591 Рік тому +1

    Method two is how I used to loop back in my 6502 days...

  • @alanbourke4069
    @alanbourke4069 Рік тому

    Sort of how we used to do things in assembler, then.

  • @adrian_franczak
    @adrian_franczak Рік тому

    “It’s enough slices!”(loop perf videos)

  • @HarshColby
    @HarshColby Рік тому

    Effectively, the fastest way is equivalent to the fastest original C way: get a pointer to the start, and add the item size. Doesn't surprise me.
    Using spans isn't as clear to people looking at the code (yet), so I know span is there but I almost never need them.

  • @clantz
    @clantz Рік тому +1

    Have you also tried dropping into unsafe code and using actual pointers? Would be interesting to see.

  • @EtienneFortin
    @EtienneFortin Рік тому

    How about pointer arithmetics, aka true unsafe code? How much faster would it be? Or would it be any faster than Faster loop? And would the array need to be pinned?

    • @nickchapsas
      @nickchapsas  Рік тому +2

      That’s the topic of the next loop video

  • @pharoah327
    @pharoah327 Рік тому

    Is array indexing really so slow that calling a function each iteration is faster? Even with spatial locality caching and bus sizes that can return multiple contiguous elements at a time? My intuition would be that the stack frame hit from a function call (pushing the popping the activation record, moving around the program counter, loading and unloading arguments) would be more expensive then the frequent L1 cache hits (or pulling from registers) from array indexing (i.e. ask for one value in array, it grabs multiple values, amortized cost is very low overall). I'm fully aware that I am missing something but what is it that I'm missing here?

    • @maschyt
      @maschyt Рік тому

      There are no function calls when the code gets executed. The methods used are so simple that they get inlined automatically and/or have [MethodImpl(MethodImplOptions.AggressiveInlining)].

    • @user-od4ce8pe3u
      @user-od4ce8pe3u Рік тому +1

      I think you miss inlining. All this unsafe... cals would be probably inlined. Also this approach is so fast, because you work with array on memory level, so for example code will not check for index out of range exception and so on.

    • @pharoah327
      @pharoah327 Рік тому

      @@user-od4ce8pe3u that's a good point! Thanks

  • @Rafloka
    @Rafloka 6 місяців тому

    Oh man, here I am totally not optimizing prematurely.

  • @DanielCipra
    @DanielCipra Рік тому

    I have to push this to some branch and then let someone CR this loop :D

  • @debtpeon
    @debtpeon Рік тому

    This is exactly how you do it in C & C++

  • @DennisHaney
    @DennisHaney Рік тому

    Isn't it enough to just put the items.Length in a variable, so that it does not need to be evaluated in each loop?

    • @nickchapsas
      @nickchapsas  Рік тому

      Nop. In these examples it won't make a difference at all

    • @1nterstellar_yt
      @1nterstellar_yt Рік тому

      there is a special IL code for getting array length

    • @sgbench
      @sgbench Рік тому

      The compiler is smart enough to do that behind the scenes

  • @user-wx7yx5nw9j
    @user-wx7yx5nw9j Рік тому +3

    Eventually it becomes c++ iterators xd

  • @1Eagler
    @1Eagler Рік тому

    Welcome C

  • @fredhair
    @fredhair Рік тому +1

    If you ever need this level of performance you should probably be using C++ and doing your pointer arithmetic there! C# goes out of it's way to make this sort of low level code from being used though it is interesting to see it's possible to do it. When you have a problem you wish to solve with code, you should consider what is the best tool for the job and this often means some languages are better suited than others.
    Very cool video & as others have said, good job putting the disclaimer at the start, I've seen developers who want to do stuff like this when performance isn't an issue. For the sanity of dev teams everywhere, readibility & good structure is more important than premature optimization.

  • @keit99
    @keit99 Рік тому

    Ah good old C-territory spaghetti code

  • @enitalp
    @enitalp Рік тому

    Put length in a const variable and not in the loop.

  • @user-de2px1ed8k
    @user-de2px1ed8k Рік тому +1

    Not so proficient in C# and it's history. So why again Microsoft can't make for/foreach loops as fast as this method as they did with said for/foreach in .Net 7?

  • @ronosmo
    @ronosmo Рік тому +1

    I don't bother optimising loops in c#.. It was normal practice in my c & c++ days - but foreach is so much cleaner and less error-prone - it's not worth the effort! Besides the new syntax is much less concise than the original C versions.

  • @morriscurtis
    @morriscurtis Рік тому

    You could try caching the items.Length before the loop, that might make the span approach faster also at 10000 items (haven't tried it myself though)

    • @nickchapsas
      @nickchapsas  Рік тому

      It isn't going to make a difference at all for those sizes

  • @vabka-7708
    @vabka-7708 Рік тому +1

    FasterLoop is not Faster than "normal" in last run. Check deviation

  • @SIlaelinAndCo
    @SIlaelinAndCo Рік тому

    I feel like you could just use C or C++ at this point

  • @ad9291
    @ad9291 Рік тому

    Feels like a Linked List with extra steps

  • @Tal__Shachar
    @Tal__Shachar Рік тому

    C Dull

  • @deltaphilip8611
    @deltaphilip8611 Рік тому

    hmm, change the order you run the methods.

  • @thx1137
    @thx1137 Рік тому

    I really hate it when people use the word “lie” instead of “wrong”. One is on purpose and the other isn’t. If the other video was truly a lie then that makes all the videos suspect.

    • @nickchapsas
      @nickchapsas  Рік тому

      I agree with you but that’s not how the UA-cam algorithm and click through rates work unfortunately. It’s the game we have to play (and it’s sad but it works)

  • @donelbaron
    @donelbaron Рік тому

    don't see any value in this kind of topics

    • @nickchapsas
      @nickchapsas  Рік тому +2

      I think there is value knowing that you can go deeper in C#. Game developers using Unity or people doing image processing, HEAVILY use these techniques to optimize their code.