There are a lot of upcoming performance changes in .NET. Starting from code generation (JIT, AOT) and optimizations that can be performed by the compiler (inlining, flowgraph & loop analysis, dead code elimination, SIMD, stack allocation and so on). In this talk we will cover some features of C# 7 are going towards making low level optimization.
I will share not only how we can improve performance with the next version of .NET, but how we can do it today using different techniques and tools like Roslyn analyzers, Channels (Push based Streams), System.Slices, System.Buffers and System.Runtime.CompilerServices.Unsafe.
Powerful Google developer tools for immediate impact! (2023-24 C)
Игорь Фесенко "Direction of C# as a High-Performance Language"
1. Direction of C# as a High-
Performance Language
Igor Fesenko
SoftServe Inc.
@ky7m
2. Who am I?
• Leading software development
projects
• Passionate about high burst/HPC
systems
• Design cloud ready software solutions
• SoftServe .NET Community leader
• Conference speaker and trainer
• More… go to ifesenko.com
5. • Productivity and ease of use
• Built-in safety
• Powerful async and concurrency models
• Mature ecosystem of tools and libraries
Why C#?
@ky7m #dotnet
#fwdays
24. A. All options are correct
What is the correct C# syntax to declare
the getter-only auto-property ?
Opt. 1 - public int Property1 => 42;
Opt. 2 - public int Property2 { get => 42; }
Opt. 3 - public int Property3 { get { return 42; }
B. Options 1 and 3
C. Option 3 D. I’m Java developer
25. A. All options are correct
D. I’m Java developer
What is the correct C# syntax to declare
the getter-only auto-property ?
Opt. 1 - public int Property1 => 42;
Opt. 2 - public int Property2 { get => 42; }
Opt. 3 - public int Property3 { get { return 42; }
26. A. All options are correct
D. I’m Java developer
What is the correct C# syntax to declare
the getter-only auto-property ?
Opt. 1 - public int Property1 => 42;
Opt. 2 - public int Property2 { get => 42; }
Opt. 3 - public int Property3 { get { return 42; }
35. • Available on Nuget -
https://www.nuget.org/packages/FastMember
• Open-source -
https://github.com/mgravell/fast-member/
• Uses ILGenerator and SiteCall power
FastMember
@ky7m #dotnet
#fwdays
36. FastMember Example Usage
var
string // smth known at runtime
while /* some loop of data */
// obj could be static or DLR
var
string // smth known at runtime
@ky7m #dotnet
#fwdays
39. Unsafe class api
public static class Unsafe
// all methods are public static unsafe
void
void void value
int
object where class
void ref value
ref void
void InitBlock void byte uint
void CopyBlock void void uint
ref void
@ky7m #dotnet
#fwdays
40. With Unsafe you’re more Safe
var 10
var ref //void*
var int // int
@ky7m #dotnet
#fwdays
41. • One Really Big Query Expression (60-line query)
• A lot of LINQ To * (what you want)
LINQ is fantastic feature of C#!
@ky7m #dotnet
#fwdays
45. • https://github.com/antiufo/roslyn-linq-rewrite
• Works at compile time (build step)
• No code changes
• No allocations for Expression<> trees and
enumerator boxing
• Parallel LINQ is not supported
RoslynLinqRewrite
@ky7m #dotnet
#fwdays
46. • https://github.com/dotnet/corefxlab/tree/master/src
/System.Slices
• Span is a simple struct that gives you uniform access
to any kind of contiguous memory
• It provides a uniform API for working with:
• Unmanaged memory buffers
• Arrays and subarrays
• Strings and substrings
• It’s fully type-safe and memory-safe.
• Almost no overhead.
Span (Slice)
@ky7m #dotnet
#fwdays
47. Make subslices without allocations
byte stackalloc byte 256
var new byte 256
char new char ’ ' 'N' 'E' 'T'
char new char
char
0 4
@ky7m #dotnet
#fwdays
48. • Nuget -
https://www.nuget.org/packages/System.Buffers/
• ArrayPool
• resource pool that enables reusing instances of T[]
• managed memory
• NativeBufferPool (experimental, under corefxlab)
• Unmanaged memory
• pool of Slice<T>
System.Buffers
@ky7m #dotnet
#fwdays
49. • Get your own instance
• ArrayPool<T>.Shared (Thread safe)
• NativeBufferPool<byte>.SharedByteBufferPool (Thread
safe)
• ArrayPool<T>.Create(int maxArrayLength, ..)
• Rent
• Specify the min size
• Bigger can be returned, don’t rely on .Length
• Finally { Return }
• Alternative - Microsoft.IO.RecyclableMemoryStream
• Provide pooling for .NET MemoryStream objects
• Limited usage
How to work with Pools
@ky7m #dotnet
#fwdays
50. • Heap allocation viewer
Heap Allocations Viewer R# plugin
Clr Heap Allocation Analyzer VS extension
• Roslyn analyzers
https://github.com/dotnet/roslyn-analyzers
https://github.com/Wintellect/Wintellect.Analyzers
https://github.com/DotNetAnalyzers/StyleCopAnalyzers
• Annotations
[StackOnly] - Microsoft.CodeAnalysis.StackOnlyTypes
[NoAlloc] ensures a method doesn’t allocate
[MustNotCopy] ensures a struct isn’t copied
[Scoped] ensures a value doesn’t escape the callee
... and more ...
Essential tools in your toolbox
@ky7m #dotnet
#fwdays
51. • C# delivers productivity and safety, good
performance from JIT to AOT and everything in
between
• A lot of features are “free”
• Structs can improve memory performance
• Less GC pressure
• Better memory locality
• Less overall space usage
• Beware of copying large structs, “ref returns”
• New features in next rev of C# and .NET: ValueTask,
ValueTuple, others
• Use power of Roslyn
Summary