Writing Allocation Free Code in C# - Matt Ellis

preview_player
Показать описание
Performance is a feature. We all want our code to run faster, and there are plenty of ways to do this - caching, using a smarter algorithm or simply doing less stuff.

In this session, we’re not going to look at any of that. Instead, we’re going to focus on a recent trend in the C# world - improving performance by reducing memory allocations. We’ll see how recent versions of C# allow using structs without creating lots of copies, and we’ll have a timely reminder on exactly what is the difference between a class and a struct. We’ll also spend some time with the new Span<T> runtime type and find out how that can help work with slices of existing memory, and how it’s already into the types we know and love in the framework. And of course, we’ll take a look at when you should and (more importantly) shouldn’t use these new techniques.

Check out more of our talks in the following links!

NDC Conferences
Рекомендации по теме
Комментарии
Автор

I applied this to my code today - and got a performance gain that looks like an order of magnitude!

HenrikRClausen
Автор

I really like the presentation where Matt covers the basics of CS such as boxing, reference and value types in relation to memory allocation to explain the performance issues is simple yet insightful. Thank you.

AnitShrestha
Автор

Finally someone brings it up! This is important for gamedev since gc introduces stutter where you always want a smooth framerate. The thing I miss most is Linq

osten
Автор

34:12 Defensive copy on method calls:

At the time of this talk ( June 2019 ) the feature called "readonly members" did not exist yet. It premiered in C#8 in September 2019.
Readonly members allow to mark methods and property getters on structs as readonly and the compiler enforces that these methods do not change the internal state of the struct.
Accessing readonly members avoid the defensive copy on structs that are not as a whole readonly.

sealsharp
Автор

Wow, such a great presentation with lots of advanced concepts, thank you for all this Matt, appreciate it!!!

vkg.codefactory
Автор

Very useful talk, got some "gotcha moments" out of it even though I studied all the new features from C#7 on.

I'd like to correct not a mistake, but a not so great choice of words made in the video, at around minute 10:00 - the default passing of variables to methods is always by *value*, be them ref or value types.

In the specific case of value passing a reference type variable, the value that is passed (thus copied) into the local scope parameter is the reference itself, and that ofc means that, even though the original argument and the local parameter are different (since the local param is a copy of the original argument), they both point to the same object in the heap.
And this brings the fact that local changes to the data contained in the referenced object are reflected outside the local scope.

Just wanted to point this out, cause it can cause some confusion. ;)

galandilvogler
Автор

C# slowly turns into C++.. the better part of it :)

phobos_
Автор

Fantastic talk! This is exactly the kind of content I have been searching for!

FastFSharp
Автор

Cool!!!! TNX! - I will make use of it - although my program´s performance gaps are most times I/O-related. But I like this ref/in/out - and Span<char> will replace string in all bigger string-operations. For POCOs I will still use strings. It´s such a pity that Span<T> implements NO Changed-Event. (A quick intro into GC... where it lives, runs, gets started, if it still runs for clean-up while Main-App has already been terminated... could be very useful)

lollo
Автор

Perfect talk related to C# performance. Now C# and C++ equal in performance using these techniques.

sergekgkg
Автор

A bit off topic, but compiler enforced readonly reference types . I realise it might be a bit of a pain because of inheritance. But it would be really nice to have.

kobbyg
Автор

@8:50 This doesn't only happen with boxed value types. Boxed or not boxed, any value type you pass in to a method that mutates that value, the changes won't be observed outside the method (unless you used out/ref). @9:45 I think it should be made more clear that value types are allocated on the stack, or the heap. I know it says in small writing "or embedded into a reference object", but the misconception that "value types go on the stack" is too common, and this kind of adds to it by having the second explanation in smaller writing. @18:38 reference and value types are both cheap to allocate. It's the DEallocating that is expensive for reference types, and involves GC.

davidklempfner
Автор

This was commented on by another user but it really needs to be repeated. In C# parameters are passed in by value by default. Reference objects are NOT passed by reference. For reference objects the value just happens to be the reference. Two different places in memory that reference the same place the object is at. If you want something passed by reference you have to use the "ref" keyword.

logank.
Автор

I want a Span<T> that works with files and memory mapped files.

th_CAV_Trooper
Автор

hmm, I'm definitely agree on reuse of same object instead of new initialization allocation, just notice System.Text.Json is only available in .NET Core 3? Between not sure how is this useful to few things like List<T> where I need to do data manipulation a lot when come to relational parent child model, and StringBuilder to enhance with Span<string>? Not sure IDBConnection can be pass by ref to reduce allocation?

wim
Автор

thumb up for the initial DON'T and measure it

LuigiTrabacchin
Автор

Is there any tool or option in Visual Studio that can produce the warning of delegate allocation, like the warning "Delegate allocation: capture of 'name' parameter" in the slide at 12:54?

sken
Автор

I cannot start to imagine to rewrite all the linq expression to foreach and if...

wim
Автор

So much for user friendliness of managed languages :)))
So the next step is to introduce manual memory management, C++ RAII style. Oh wait, "using" is basically just that)) I like "using" without the braces. feels almost like C++ :)
Or we could just go back to C++ )))

zariumsheridan
Автор

All of the issues highlighted are why a language should be designed from the ground up to handle all of these things. Instead, they copied Java, which was highly constrained and foolishly so, and extended it with incompatible features from C++, and have had to continuously extend the language to add features that are hacked on to keep up with where developers want to go. So now, we have hot garbage on toast for pretty much every language, because of course, Java, C++ and many more have hacked on kludges to try and keep up. Not that I'm saying a new language should be designed and built every few years to keep up, but maybe we shouldn't try to keep up at all. C is still perfectly fine as a language, it just doesn't have syntactic sugar to handle everything, but it also doesn't have *huge quantities* of gotchas that make programming anything complex a minefield.

anon_y_mousse