53
Direction of C# as a High- Performance Language Igor Fesenko SoftServe Inc. @ky7m

Игорь Фесенко "Direction of C# as a High-Performance Language"

  • Upload
    fwdays

  • View
    625

  • Download
    1

Embed Size (px)

Citation preview

Direction of C# as a High-Performance LanguageIgor FesenkoSoftServe Inc.

@ky7m

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

“Performance of my code is awesome.”

Developer

“…premature optimization is the root of all evil…”

Donald Knuth

• Productivity and ease of use

• Built-in safety

• Powerful async and concurrency models

• Mature ecosystem of tools and libraries

Why C#?

@ky7m #dotnet

#fwdays

Problem?

@ky7m #dotnet

#fwdays

.NET

@ky7m #dotnet

#fwdays

.NET

Problem?

@ky7m #dotnet

#fwdays

• Garbage collection

• Allocation-rich APIs and patterns

Why Not C#?

@ky7m #dotnet

#fwdays

Memory Allocations Everywhere

Code Generation

@ky7m #dotnet

#fwdays

• Just-In-Time (JIT) - CoreCLR

• fast compile times

• simple

• decent code quality

• Ahead-Of-Time (AOT) - CoreRT

• best code quality

• slower compile times

• complex deployment model

• Hybrid [Future]

• let the system adaptively recompile

Code Generation

@ky7m #dotnet

#fwdays

Code Generation

JITAOT

AOT

@ky7m #dotnet

#fwdays

• Inlining

• Flowgraph and loop analysis

• Range analysis

• SIMD and vectorization

• Dead code elimination

• …

/optimize+

@ky7m #dotnet

#fwdays

Inlining

• New stack frame

• Save return address

• Save registers

• Call

• Restore context

@ky7m #dotnet

#fwdays

Inlining

int tmp = a; a = b; b = tmp;

void Swap<T>(ref T a, ref T b)

{

T tmp = a; a = b; b = tmp;

}

@ky7m #dotnet

#fwdays

Allocation

• Allocates up to 2 objects

• lambda

• captured stack frame

@ky7m #dotnet

#fwdays

Stop the world!

@ky7m #dotnet

#fwdays

• Generational, compacting garbage collector

• Large Object Heap (LOH) manually only

• Manual “low pause” regions

• LowLatency

• TryStartNoGCRegion

• Parallel collector for server workloads

• Server mode

• .NET 4.5 concurrent + parallel in harmony

Garbage Collection

@ky7m #dotnet

#fwdays

• Language Feature Status

• C# 7.0

• Binary Literals

• Digit Separators

• Local Functions

• Type switch

• Ref Returns

• Tuples

• Out var

• ValueTask

• …

C# 7 Features

@ky7m #dotnet

#fwdays

Who wants to be a Millionaire?

C# 6.0 Quiz

@ky7m #dotnet

#fwdays

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

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; }

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; }

Local Functions

@ky7m #dotnet

#fwdays

Local Functions

List<T> items,

values

values,

• Value Type to build closure

@ky7m #dotnet

#fwdays

Ref Returns

@ky7m #dotnet

#fwdays

Ref Returnsref

ref

ref ref

place = 9;

WriteLine(array[4]); // prints 9

@ky7m #dotnet

#fwdays

Tuples

• New Tuples are value types

@ky7m #dotnet

#fwdays

• Struct type

• Not replace Task, but help to

• drastically reduce the number of allocations

• method inlining

ValueTask<T>

@ky7m #dotnet

#fwdays

The hardest problem in computer science is fighting the urge to solve a different, more interesting problem than the one at hand.

Nick Lockwood

• Exposes implementation details

• Code Complexity

• Obscures Logic

• Missing Static Checks

• More Exception Handlers

• Security

• Performance

Problems with Reflection

@ky7m #dotnet

#fwdays

• 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

FastMember Example Usagevar

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

FastMember and SqlBulkCopyvar newvar

@ky7m #dotnet

#fwdays

• Nuget -https://www.nuget.org/packages/System.Runtime.CompilerServices.Unsafe/

• Low-level functionality for manipulating pointers

• Whole code is single IL file

System.Runtime.CompilerServices.Unsafe

@ky7m #dotnet

#fwdays

Unsafe class apipublic 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

With Unsafe you’re more Safevar 10

var ref //void*

var int // int

@ky7m #dotnet

#fwdays

• 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

Even R# helps…

@ky7m #dotnet

#fwdays

• Hidden allocations

• Possible multiple enumeration

• Easy to write a non-optimal query

LINQ downsides

@ky7m #dotnet

#fwdays

• Nuget -https://www.nuget.org/packages/LinqOptimizer.CSharp/

• Works at run-time

• Requires AsQueryExpr().Run() to LINQ methods

• Optimizes Parallel LINQ

• Specialized strategies and algorithms

LinqOptimizer

@ky7m #dotnet

#fwdays

• 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

• 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

Make subslices without allocationsbyte stackalloc byte 256

var new byte 256

char new char ’ ' 'N' 'E' 'T'char new char

char0 4

@ky7m #dotnet

#fwdays

• 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

• 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

• Heap allocation viewerHeap Allocations Viewer R# pluginClr Heap Allocation Analyzer VS extension

• Roslyn analyzershttps://github.com/dotnet/roslyn-analyzershttps://github.com/Wintellect/Wintellect.Analyzershttps://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

• 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

• https://github.com/dotnet/corefx

• https://github.com/dotnet/coreclr

• https://github.com/dotnet/corefxlab

• https://github.com/dotnet/roslyn

• https://github.com/dotnet/corert

• https://github.com/dotnet/coreclr/blob/master/Documentation/botr/readytorun-overview.md

Links

Questions

@ky7m | ifesenko.com | [email protected]