Writing C# without allocating ANY memory

Поділитися
Вставка
  • Опубліковано 30 бер 2022
  • 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 how you can use features such Span, ReadOnlySpan and stackalloc to write allocation free C# that is very fast. This video will just focus on a single example but I will explain every decision as I go and hopefully you will find areas where you can use the technique you see here to optimize your own code.
    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 #performance

КОМЕНТАРІ • 338

  • @RoughSubset
    @RoughSubset 2 роки тому +253

    Definitely want to see more content like this, thanks Nick for constantly expanding my mind. I just want to say I'm probably about 10 years older than you but I have no shame in saying that you are a great teacher and I learn a lot from you, I always promote your videos at work.

    • @brentsteyn6671
      @brentsteyn6671 2 роки тому +10

      I also promote his video's at work. 😁

    • @shawnelswick5715
      @shawnelswick5715 2 роки тому +8

      Yep, I third this, lol

    • @akeemaweda1716
      @akeemaweda1716 2 роки тому +1

      I equally do share his videos with my colleagues and other programmer friends.

    • @RuiNogueiraHB
      @RuiNogueiraHB 2 роки тому +1

      Me Too, also promoting his courses

  • @IAmFeO2x
    @IAmFeO2x 2 роки тому +136

    Great example! Well done Nick!
    BTW: when your process runs in 32 Bit mode, the default thread stack size is 1MB. In 64 Bit mode it's 4MB.

  • @joephillips6634
    @joephillips6634 2 роки тому +68

    I would be interested in seeing json serialization/deserialization techniques that are more memory efficient. Especially when receiving back large json payloads that need to be deserialized to an object.

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

      exactly what I was thinking about!

    • @SudhanshuMishraTheOne
      @SudhanshuMishraTheOne 9 місяців тому +5

      I reckon you’d use System.Text.Json as it is built with similar optimisations as this video.

  • @Nate77HK
    @Nate77HK 11 місяців тому +7

    One thing the Primeagen always mentions about garbage collected languages is that the performance gains of having fewer allocations won't show up in spot tests like this, because the garbage-collector pass didn't get timed in the stopwatch.
    So the optimized methods clocked in way faster but also shorten the timing on the garbage collector. Not sure if that also applies to C# like it does to JS

  • @brianm1864
    @brianm1864 2 роки тому +86

    No matter how much I think I know, I always learn something from your videos! Thanks for continuing to put out great content!!

  • @7th_CAV_Trooper
    @7th_CAV_Trooper 2 роки тому +7

    the new span and memory types are making the old C programmer in me happy

  • @BlueRaja
    @BlueRaja 2 роки тому +55

    Prior to 2019, allocation-free code was *essential* in Unity (the game engine), which ran on a 12-year-old version of Mono with single-threaded garbage collection. Having too much garbage would result in stuttering.
    To work around this issue, in 2015 Unity introduced "IL2CPP", a compiler which takes the compiled C# IL code and compiled it into C++, and then compiled *that* into a native binary. No, this is not a joke; it's a real thing that still exists.
    However in 2019 they finally upgraded to a version of Mono with multi-threaded GC, so IL2CPP is less useful. It's still a good idea to minimize allocations, though.

    • @RedHotBagel
      @RedHotBagel 2 роки тому +7

      I don't think that was or is the primary reason for IL2CPP....

    • @IgnoreSolutions
      @IgnoreSolutions 2 роки тому +4

      Yeah definitely not the only reason for IL2CPP. iOS sticks out, as you can currently ONLY build Unity games for iOS using IL2CPP. Android supports the Mono runtime or IL2CPP.

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

      still an older version of mono, but at least not ancient

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

      Now you have burst wich converts IL/.NET bytecode to highly optimized native code using LLVM, but to get the most of it, you have to write in a subset of c# called high performance c#. It is c# but with no reference types.

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

      Now with .NET 7 we have Native AOT!
      Even without it, RyuJit can output some very optimized assembly if you know what you're doing.

  • @volan4ik.
    @volan4ik. Рік тому +9

    Some tips on this video:
    1) there is a Guid.TryWriteBytes() method that acts without allocation
    2) you can use string.Create() to fast allocate the strings based on Span, instead of calling string constructor

  • @sylascoker1483
    @sylascoker1483 2 роки тому +1

    This is amazing! Learnt a lot of things that I’ve heard about but didn’t really know, keep up the good work!

  • @macgyverswissarmykni
    @macgyverswissarmykni 2 роки тому +35

    C# is starting to feel more and more like Rust. Thanks for taking the time to walk us through this.

    • @berylliosis5250
      @berylliosis5250 2 роки тому +2

      Add first-class sum types and late interface implementation/orphan rules to the lang, and ideally offer niceties like the One True Constructor and a true no-null mode, and C# becomes very attractive indeed

    • @rafaelrosa3841
      @rafaelrosa3841 2 роки тому +4

      @@berylliosis5250 i give another name to this, feature hell. The language is getting more and more complex, if i want rust, i use rust instead, is far more performant from scratch.

    • @berylliosis5250
      @berylliosis5250 2 роки тому +7

      @@rafaelrosa3841 That's a fair point, but the whole "small and simple language" ship has _very_ much already sailed for C#.
      As for using Rust instead - sure, but C# has different design constraints that are genuinely better at some things, so providing the "common" things that are really nice makes it nicer to use when necessary. (E.g. for use with Godot, which has a threading model that broadly disagrees with safe Rust)

    • @RedHotBagel
      @RedHotBagel 2 роки тому +5

      @@rafaelrosa3841 Rust has the borrow checker and with that another memory management model. C# is and will always be a Garbage Collected Language. This makes for very different ergonomics, ever if they share features.
      One's hell is the other persons heaven. The recent additions to the language have all been aimed at reducing boilerplate and reducing error potential. And for all of them, I think one thing applies: If you read the code using these features you'd be hard pressed to assume it does something else than what it does.. And that's imho the most important thing.

    • @rafaelrosa3841
      @rafaelrosa3841 2 роки тому +1

      @@RedHotBagel I don't agree with this, more features to do the same things differently only will kill the homogeneous code base to a more extensive and hard to read language, for me give a different name to a Apple killing one p (aple) Wich mean now i writing less to describe the same thing will not help, I already know what apple means it's just now have two ways of describe it, and more ways to describe the same thing will increase the learning curve of the language.

  • @malsmith69
    @malsmith69 2 роки тому +12

    I'd definitely like to see more videos like this. Great example in this video. Keep up the great content.

  • @josephizang6187
    @josephizang6187 2 роки тому +2

    Nick, I really value your content. Every time I listen to you talk about some topic, I realize I don't know enough, but I finish the video knowing more than I did before. Cannot thank you enough

  • @jancarius101
    @jancarius101 2 роки тому +2

    Great video. I learned something very valuable today! Now I've got to look up stack vs heap. Hopefully Nick Chapsas is in the results. :)

  • @VasilyPavlik
    @VasilyPavlik 2 роки тому +1

    Brilliant as usual. Thank you. Your videos push people to make their minds more efficient

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

    This is great video! please do more of those! I never thought about the size of the guid.
    I am willing to pay for a course with this level of details!

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

    I wanna see more of those kind of videos for sure, thanks for sharing.

  • @jchandra74
    @jchandra74 2 роки тому

    Yes. More like this. Very good optimisation walkthrough.

  • @inzyster
    @inzyster 2 роки тому +1

    Wow, I can already think of where to use it at work. Great stuff!

  • @NagyTami
    @NagyTami 2 роки тому +1

    Thank you! For both this video and the one on the Span.

  • @DaviGn
    @DaviGn 2 роки тому

    The most insightful UA-cam channel!!
    Please more content like this, also Unsafe code :)
    Thanks very very much Nick!!!

  • @TonoNamnum
    @TonoNamnum 2 роки тому +1

    I never use structs but thanks to this video I will use them a lot more. I am starting to see the real power of structs when you just use them to compute stuff and don't store them in memory. thanks Nick great video!

  • @ProgramandoDePie
    @ProgramandoDePie 2 роки тому

    Thank you for sharing your knowledge!

  • @antonmartyniuk
    @antonmartyniuk 2 роки тому +3

    I really like using Span and Memory when appropriate. I remember using Memory for creating a zip archive from file streams. With a maximum compression I was able to make my application 2.5 times faster because of using Memory (2.5 seconds instead of 6-7)

  • @Kikeron
    @Kikeron 2 роки тому +18

    First of all, I just discovered your channel and I think it is really good and informative. Kudos.
    Now, as an old C developer (now a manager :P ) the "allocate memory" concept rang so many bells in my mind. I have a general comment on this. If you want speed, you need to go low. If you do all this you may as well go writting unsafe in my opinion. Still it is great for people to see these kind of tutorials in order to actually see how things work!

  • @underdev
    @underdev 7 місяців тому

    Props to you, you really make it look easy!

  • @WhoCaresCertainlyNotMe
    @WhoCaresCertainlyNotMe Рік тому +5

    Another thing worth mentioning is if you want your URL-safe base64 to be RFC 4648 compliant, you need to swap the replacements. Pluses should be replaced with hyphens, not underscores. Slashes should be replaced with underscores.

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

    extremely high level content, thanks!

  • @samwheat3357
    @samwheat3357 4 місяці тому

    Well done! Thank you!

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

    Wonderful .. truly high value stuff ... keep it up. 👍

  • @m3xpl4y
    @m3xpl4y 10 місяців тому

    Thank you for teaching us this

  • @wva6809
    @wva6809 2 роки тому

    This is absolutely great! This'd be an amazing way to optimize azure function apps

  • @reza.kargar
    @reza.kargar 2 роки тому +1

    Cool content,
    Thanks for your great videos

  • @insertoyouroemail
    @insertoyouroemail 2 роки тому

    I don't use C# anymore but I'm impressed how far it's gotten since I used it many years ago.

  • @AlFasGD
    @AlFasGD 2 роки тому +54

    About the constant characters; I'd even consider it worse to create character constants mapping them to their names. You already know that '=' is the equals sign, and it's the glyph itself you care about when replacing them in base 64. It would be good practice if that '=' character represented some special sentinel that acts like a magic value, a special value encoded in the same data type.

    • @benjaminschug5572
      @benjaminschug5572 2 роки тому +22

      I was just going to say the same. It would make sense to define PaddingReplacement, PlusReplacement and SlashReplacement because that's where you're deviating from / overriding the standard and you may want to make it configurable. But this way you just make the reader doubt if the constants actually contain what their names claim to contain.

    • @NedMorse
      @NedMorse 2 роки тому +1

      I assume we all know and agree that const’s provide some benefits including being included in the assembly at build time and also being able to view occurrences referencing the const, allowing easy renaming/ better refactoring as opposed to hard coded literals.

    • @IAmFeO2x
      @IAmFeO2x 2 роки тому +11

      @@NedMorse I agree on the occurrence and refactoring argument, but it doesn't matter if you have a const field, const variable, or simply use the literal. The resulting assembly code is the same. IMO as these constants are private and they are only used once, it is a choice of style, and I tend prefer AlFas's and Benjamin's suggestion.

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

      I'm going to concur with AlFas and Benjamin Schug as well. Characters are self-identifying constants already. If you're going to give them another name, give them the name of what they're representing. Replacing `'=`` with `Equals` is just obfuscation. Replacing it with `Base64PaddingCharacter` tells the reader why you're appending an equals without actually needing to tell them what the character even is.

  • @marna_li
    @marna_li 2 роки тому

    This is very useful! Thank you for sharing..

  • @Lmao-ke9lq
    @Lmao-ke9lq 2 роки тому

    I reallly like this kind of content, pitty i didnt run into this channel earlier

  • @KonstantinKuda
    @KonstantinKuda 2 роки тому

    This is great! Thanks a lot.

  • @jbravobr
    @jbravobr 2 роки тому

    Great video nick !!!!

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

    Really videos like this opens yours eyes on you do wrong 😅. Thank you

  • @Cristian-ek7xy
    @Cristian-ek7xy 11 місяців тому

    Amazing content. More like this please

  • @asicdathens
    @asicdathens 2 роки тому

    I write different type of C# apps, worked since VS 2001 with C#, I had to use strange memory allocations twice and that was for a multichannel (80+) audio streaming application.

  • @expertreviews1112
    @expertreviews1112 2 роки тому

    Awesome content!!

  • @SpaceShot
    @SpaceShot 2 роки тому

    Love how you emphasized "when you need to"...

  • @sanderdam7655
    @sanderdam7655 2 роки тому

    Great video!
    But what if I want to remove some characters from a Span?
    And what if I want to replace a sequence of chars with one specific char?

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

    You’re literally god of c#, thanks for existing

  • @tehsimo
    @tehsimo 2 роки тому

    very informative!

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

    wow! thats cool! thank you!

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

    Hi Nick. Amazing video as always. Do you have any safe vs unsafe code video for C#? That would really help us folks out. Thanks.

  • @alexpablo90
    @alexpablo90 2 роки тому

    Excelente content!!

  • @ivaniliev93
    @ivaniliev93 2 роки тому

    well done!

  • @siavash2176
    @siavash2176 2 роки тому +10

    Thanks for great video! I love Span and Memory.

    • @siavash2176
      @siavash2176 2 роки тому

      Memory, array, and string builder pools

  • @kaiserbergin
    @kaiserbergin 2 роки тому

    seeing chained replaces... i think i know where this is going lol. great content.

  • @eyassh6747
    @eyassh6747 2 роки тому

    Great video. I was actually discussing url safe Id's with my professor today say..do you have tutorials for ASP.NET and Memory management in C# I really want to dive into this

  • @urbanelemental3308
    @urbanelemental3308 2 роки тому

    Love it.

  • @antonsmolkov751
    @antonsmolkov751 2 роки тому

    Thank for the video, Nick.
    It’s a pity that Span doesn’t work with async methods. (Can’t be members of heap objects which async state machine is)

    • @nickchapsas
      @nickchapsas  2 роки тому +1

      The state machine is a struct in release mode, it’s just not a ref struct

  • @JeanFrancoisDesrosiers
    @JeanFrancoisDesrosiers 2 роки тому

    That's next level stuff

  • @Grenefeld
    @Grenefeld 2 роки тому +2

    That youtube link example 🤦‍♂, it got me

    • @BillyBraga
      @BillyBraga 2 роки тому

      Wow, you took the time to type that out and got punished 🤣

  • @agustinbasilio5447
    @agustinbasilio5447 2 роки тому

    Nice!

  • @denizcancgsar2810
    @denizcancgsar2810 4 місяці тому

    Also it would be even faster if you convert to/from base64. It's just a lookup.. You were walking through the bytes/chars for replacement. You may use that time you to convert with a lookup table..

  • @OlaBacker
    @OlaBacker 2 роки тому

    Amazing

  • @CricketThomas
    @CricketThomas 2 роки тому

    MORE PLEASE

  • @zummygummi
    @zummygummi 2 роки тому +27

    I would be interested in seeing if what difference replacing new string() with string.Create() would make in both memory and performance.

    • @hasmich
      @hasmich 2 роки тому

      Of course it depends on hardware, OS and .NET version, but my tests (i7-9850H, win 10, .net 6) shown that string.Create is slower. No difference in memory allocation.

  • @sajagjain7169
    @sajagjain7169 2 роки тому

    Hey Nick, How do we preserve benchmarked code and keep code duplication low? Do we create these methods in test project?

  • @SchmataB
    @SchmataB 2 роки тому

    is it possible to use Benchmark in existing application to measure parts of code that are not so easy to extract into separate console test app? use case would be to collect measurements of code that you suspect is the root of all evil before refactoring that would allow to benchmark those parts in more isolated way. of course you can use dotTrace or similar profiling tools but maybe Benchmark or other package could be of use as well here?
    and as always, this video was great, keep them coming!

  • @neociber24
    @neociber24 2 роки тому

    I was waiting for a pointer I'm any time, but we still safe.

  • @JulianMoschuring
    @JulianMoschuring 2 роки тому +1

    Tip for writing allocation free code: At least in Rider you can set a different highlight color for struct types. I have structs green and class orange.
    Additionally the `Heap Allocations Viewer` plugin is really great.

    • @nickchapsas
      @nickchapsas  2 роки тому

      Just because something is a value type it doesn't mean it will be a stack allocation so the colour highlighting advice is misleading. HAV is good though

    • @JulianMoschuring
      @JulianMoschuring 2 роки тому +2

      @@nickchapsas no, but knowing if something is a value or a ref type is essential to be able to reason about allocation and performance characteristics and having different highlights makes this a lot easier.

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

      I do this too. Most types are the standard teal color, but structs are a neon greenish color. (dark theme).

  • @ShakirovRuslan
    @ShakirovRuslan 2 роки тому

    Will introducing a variable for indexers' calls in switch statements improve the performance?

  • @antonmartyniuk
    @antonmartyniuk 2 роки тому +2

    Looking forward to seeing unsafe version of this optimization

  • @c4ashley
    @c4ashley 2 роки тому +4

    Up until a few weeks ago, it'd been a long time since I'd touched C#, and I've only recently been doing Windows Forms in Mono on Linux. I'd spent a long time working on C/C++ and microcontroller assembly, so seeing these highly performant improvements to C# is very exciting! I'm loving the safe stackallocs to Span! If only it were implemented in Mono. 😢

    • @nickchapsas
      @nickchapsas  2 роки тому +4

      You don't need Mono. .NET is fully cross platform.

    • @c4ashley
      @c4ashley 2 роки тому

      @@nickchapsas Yeah but Windows Forms isn't. And yeah I know Avalonia is a thing, but I just wanted to quickly whip up this personal project in something I was familiar with. (In retrospect, maybe I should've spent the time to learn Avalonia and the newer .NET and C# features, but alas.)

    • @nickchapsas
      @nickchapsas  2 роки тому +3

      @@c4ashley You can use MAUI instead of WinForms.

    • @c4ashley
      @c4ashley 2 роки тому +1

      @@nickchapsas I wish. It's still unsupported on Linux, and the linux-maui community fork is a total bust in my case. Maybe one day soon. Or maybe if I spend long enough trying to solve installation problems. For now, Mono is fine. A bit buggy, a bit dated, but at least it actually works.
      Anyway, this is all tangental; I was just saying I like the features you're pointing out in this video, and I'm excited at the prospect of using them for future (non-Mono) projects! 😀

  • @marvinbrouwer459
    @marvinbrouwer459 2 роки тому +14

    Hey Nick,
    I feel like I've become pretty proficient in safe memory optimizations (which usually is more than enough).
    Especially since span got added.
    However, I never really trained the unsafe muscle and I was wondering if you can point me towards some good videos / blogs to start looking into that?

  • @FlavioO
    @FlavioO 2 роки тому

    Awesome

  • @kaksisve4012
    @kaksisve4012 2 роки тому +5

    Tiktokers: Say something without saying it.
    Nick: Access something without allocating it.

  • @manuelvalencia6705
    @manuelvalencia6705 7 місяців тому

    If i want to optimize my (real time)C# code i'd rather port it to C++. My boss doesnt think that way tho. Thanks for the knowledge

  • @jonas_hoel
    @jonas_hoel 2 роки тому +2

    Could you make a video about how dispose works (IDisposable) and how to implement it correctly?

    • @briankarcher8338
      @briankarcher8338 2 роки тому

      Keep in mind there's also IDisposableAsync. Dispose is used to release resources. Disposable objects should be put in a using statement when possible.
      The whole point of IDisposable is to use it in a using statement so it will get called when the using statement ends, even if an exception gets thrown.

  • @drewnichols7723
    @drewnichols7723 2 роки тому +31

    Is extracting the strings to constants necessary? The compiler performs automatic string interning on literals and should only allocate once for the life of the program.

    • @AndersJohansen92
      @AndersJohansen92 2 роки тому +15

      It's a style thing. An ordinary idea in programming is to avoid "magic strings" in your methods, and have all constant values at the top. As you said it doesn't do anything at all to impact speed or memory consumption.

    • @EtienneMaheu
      @EtienneMaheu 2 роки тому +33

      ​@@AndersJohansen92 As a style thing, this video shows exactly how NOT to do it correctly. A couple of points:
      - Replacing '/' with `Slash` is akin to replacing `42` with `FourthyTwo`. It doesn't provide any value and definitely doesn't respect the idea behind the no-magic-literals rule which is to make sure that all of your literals are *described* in your code. A better name for `Slash` would be `Base64_Value63` which describes what the code expects the variable to contain.
      - The cast to byte should also reuse this variable and not redeclare it from '/' again to highlight the relationship between the char and byte version. In this example, one could decide to replace the '/' with another char but forget to do it on the other way around. This would prevent decoding from working correctly.
      - The fact that the compiler already handles this for you is not mentioned in the video. This means that most people will watch this video and think that those const extractions actually helps with the performance of this code, which is a very common myth.
      - '+' comes before '/' in base 64, so they should be declared in that order as well. In fact, a proper variable name would also highlight this.

    • @ZelenoJabko
      @ZelenoJabko 2 роки тому +2

      @@EtienneMaheu Awesome points man. This youtuber is a total noob, he should not have a youtube channel. You would do a much better job.

    • @TedThomasTT
      @TedThomasTT 2 роки тому +8

      @@ZelenoJabko 🤡

    • @ErdoganKurtur
      @ErdoganKurtur 2 роки тому +3

      This is because of rule #1: You write code for developers, not for computers. While defining Equals = '=' is kinda pointless, it comes from a good habit where you leave not constant unchecked, so you fan find wherever you use them. Try finding where use used = as a constant with "Find in Files"

  • @gctypo2838
    @gctypo2838 5 місяців тому

    1:24 Wasn't the URL I was expecting but still got the expected result.

  • @DmitryV_HF
    @DmitryV_HF 2 роки тому +1

    Do we can update base64span array without creating finalChars? Iterate and update special chars.

  • @CharlesBurnsPrime
    @CharlesBurnsPrime 2 роки тому

    I like your low_level optimization videos in particular, but why are there no built-in URI-safe GUID methods which use safe characters as their native lexicon?

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

    very useful, but this way for reference type, have any way for value type ?

  • @oscareriksson9414
    @oscareriksson9414 2 роки тому

    Cool!

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

    Is such conversion of guid to bytes correct? What about BE/LE systems? Won't they mess bytes?

  • @berathebrain
    @berathebrain 2 роки тому

    More!

  • @shawnelswick5715
    @shawnelswick5715 2 роки тому

    Hey Nick, for some of your courses, if you have questions, what is the best way to reach out on those?

    • @nickchapsas
      @nickchapsas  2 роки тому

      Linked in, Twitter DMs or email works

  • @wuketuke6601
    @wuketuke6601 3 місяці тому

    Why did you create a const variable for backslash and plus and such? is it for maintainability?

  • @enji._
    @enji._ 2 роки тому

    Great video, but I got a bit lost when you said Span was allocated on the stack (so I thought it generally was) and still used stackalloc (in order to achieve something I thought was already the case?). What am I misunderstanding?

    • @tajkris
      @tajkris 2 роки тому +2

      Broadly speaking: Span only contains a 'pointer' to memory and bounds. That memory can still be on the stack or on the heap. Using a stackalloc you allocate memory on the stack, and then create new Span object (also on the stack) that points to that memory

  • @noylevi3340
    @noylevi3340 2 роки тому

    About making this faster:
    The conversion of the arrays in the optimised To and From, could be done in parallel..
    I guess that needs testing and benchmarked to verify improvement in speed.

    • @nickchapsas
      @nickchapsas  2 роки тому +4

      Adding multithreading or concurrency here would make it slower due to the workload being small. It's overhead with diminishing returns

  • @padreigh
    @padreigh 2 роки тому

    Your intro sounded like a aprils fool - glad I knew about Spans and stuck around ;)

  • @Gastell0
    @Gastell0 2 роки тому +1

    Would casting char to byte within the function allocate memory as well? Or you could have worked directly with const char?
    Also when was that switch introduced? First time seeing it

    • @nickchapsas
      @nickchapsas  2 роки тому

      Char and byte are value types so there would be no allocation. Switch expressions have been out for a few years now

  • @LCSL90
    @LCSL90 2 роки тому +2

    Having a full grown api already i am curious if this would improve the performance so drastically.
    I would think you have the string converted after each call of an endpoint, so basically every Guid you use now would be string something like B2yOjLyEZk0.
    Then you'd convert it back to guid and use the guid for querying database. Would be interesting to see how you would implement that into an existing api.
    I am also curious if the DI would slow things down once you implemented the function to convert guids.
    edit: i just saw you're using static.. so forget the DI.. :D

    • @nickchapsas
      @nickchapsas  2 роки тому +12

      You will really see a benefit if you are using the conversion in many areas. For example if you were allocating 200 bytes (like in the video) per conversion, then if you’re dealing with 1000 requests per second (which I do more of that) then you’re instantly on 20kb or wasted memory per second which adds up quickly and triggers collection by memory pressure. I think you should profile your apps memory and if that part is hot then optimise it otherwise, ignore it and go for the low hanging fruit. You wanna be pragmatic here

  • @PolishchukMaxim
    @PolishchukMaxim 2 роки тому

    What does it mean "without allocating ANY memory"?
    stackalloc initializes stack allocated buffers. Sure, it does not use heap.
    "without allocating ANY memory" - it is like your Span/Span exists in virtual address space of virtual address space 😀

    • @buraktamturk286
      @buraktamturk286 2 роки тому

      You don't allocate. You are using already allocated limited stack memory. No overhead for GC too.

    • @nickchapsas
      @nickchapsas  2 роки тому

      There is obviously no programming without allocations of some sort, but in C# when we talk about memory allocations we talk about heap allocations. This video shows how you can use the Span struct to mostly or solely allocate memory on the stack which is fast and cheap.

    • @PolishchukMaxim
      @PolishchukMaxim 2 роки тому

      @@buraktamturk286 when you are creating (placing) variable in stack it means that some stack memory will be allocated specially for this variable. Variable is unable to exist anywhere in "already allocated limited stack memory", this variable will have concrete address in stack memory, i.e. we have allocating of specially space for variable in stack. Keyword is stackalloc, isn't it? 😀

    • @PolishchukMaxim
      @PolishchukMaxim 2 роки тому

      @@nickchapsas It is OK. Forgive me for grabbing that screaming headline. This is a very good video. Many thanks.

    • @buraktamturk286
      @buraktamturk286 2 роки тому

      @@PolishchukMaxim well, the stack for running thread is already allocated when that thread is created. So you are using pre-allocated memory. It is just stack pointer that gets adjusted by the amount of data requested. (It is just a simple math operation on stack pointer). Name is for convention only.

  • @Soraphis91
    @Soraphis91 2 роки тому

    17:20 "there is an overload, so this iwll alocate no memory again"
    I'm not sure that this is the case. assuming it would NOT allocate memory again, then the string would point internally to memory on the stack, so it would point to memory which won't exist after the mehtod anymore. OR it would mean that this constructor implictly MOVES the memory from the span into the string.
    ALSO: the benchmark shows that it will allocate the memory on the heap, as it resulted in 76 Bytes allocated which are: 32 Byte for the empty string + 22* 2 Bytes for each of the characters.
    **edit** while listening again to you, i think I've understood you wrong the first time. I thought you meant it would only allocate the 32 Byte for the string, but would not allocate the content of the string.

  • @megasuperlexa2
    @megasuperlexa2 7 місяців тому

    why extract 'Plus' and 'Equals' to the constants?? can they ever change? Plus become minus or something?

  • @TurtleWargaming
    @TurtleWargaming 2 роки тому

    Where can I learn stuff like this? I missed a lot of this kind of stuff in my degree.

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

    Instead of copying the bytes in the Guid into a Span, can't you just cast it into a byte* in unsafe mode?

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

      We don't wanna resort to unsafe code

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

    What's the purpose of putting =, /, - in fields instead of just in the switch?

  • @cn-ml
    @cn-ml 2 роки тому +2

    When using the default case in a switch you do a second array lookup. Would it be faster to use a binding match instead of an underscore? Like char i => i instead of _ => array[pos]

    • @nickchapsas
      @nickchapsas  2 роки тому

      There is no array lookup at all with the switch. It's being lowered to if checks

    • @Krimog
      @Krimog 2 роки тому

      @@nickchapsas I had the same reaction as @Michael Chen and I must admit I don't understand your answer...

    • @nickchapsas
      @nickchapsas  2 роки тому

      @@Krimog Sorry I misunderstood the question. No that can't happen because list patterns don't work like that. You can't do i => i.

  • @thomas3141
    @thomas3141 2 роки тому +7

    Can you do a video on improving Entity Framework performance?

    • @rasimismatulin1400
      @rasimismatulin1400 2 роки тому +2

      It's interesting idea, how we can optimize for example update entity which has child and they have own child. What about batch operations and so on

    • @briankarcher8338
      @briankarcher8338 2 роки тому +1

      Dapper :)

    • @rasimismatulin1400
      @rasimismatulin1400 2 роки тому

      @@briankarcher8338 🤣🤣

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

    Thanks for the video.
    I really appreciated it that they introduced this modern style of the good old stack-based buffer programming into the "safe" area of C# programming language, it's only just a few years ago.
    As somebody who also programs in the classical C and C++ languages at certain times, I know exactly what these things mean. Everything is stack-based there by default. Very different from .NET and that makes these languages incredibly performance efficient.
    I suspect that many daily C# development may bennefit more often from these things than we are often aware of.
    We are all so used to the traditional heap reference based based array's in .NET.

  • @amrosamy8232
    @amrosamy8232 2 роки тому

    As you said at the end this could lead to stack overflow

    • @nickchapsas
      @nickchapsas  2 роки тому +2

      This would not lead to stack overflow because the memory is deterministic and extremely small. You should worry about stack overflow on lengths that you cannot control. this example will never lead to a problem. Most of the .NET code behind the scenes uses this exact practice to optimise the code

    • @amrosamy8232
      @amrosamy8232 2 роки тому

      @@nickchapsas thank you for the explanation, and thank you for that wonderful demo.
      For sure this will be useful with embedded boards and less resources computers where the performance is a main part.

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

    The part that was hard for me to understand was the switch { } with the lambda.