Methodology
-
Measure early and frequently
-
Focus on critical paths
Framework specifics
-
Beware of
Exception
throwing performance cost -
Avoid string manipulation, use
StringBuilder
or better alternative -
Avoid Reflection
-
Careful with
foreach
loop (state machine allocation) -
Careful with
async
(state machine allocation)
Beware of Lock contention
-
See LMAX Disruptor
lock
vs atomic write vs single thread benchmarks -
Queue induce a lot of contention
Object Reuse
- Object caching
Object Pooling
-
Promote
ArrayPool
-
Promote
RecyclableMemoryStream
Avoid Allocation
-
async
- useValueTask
when high probability to return the task result directly -
Avoid closures in lambda
-
Avoid yield (state machine allocation)
-
Avoid LINQ
-
Promote allocation on stack -
stackalloc
and/orSpan<T>
for temporary local data storage -
Promote
ValueTuple
, being astruct
-
Promote
struct
-
Allocating a reference type has a cost, but passing it around is cheap, allocation a value type is cheap, but passing it around has a cost (which can be handled using a
struct
ByRef) -
Thread safe
-
JIT optimization
-
Avoid boxing of value types
-
Use generics with constraints
Do<T> where T: ISomething
-readonly struct TImplem: ISomething {}
, which is JIT optimization friendly -
use
readonly
,ref
andin
keyword for flexibility, both as function parameter and return value signature-
ref
: pass by reference, property modification allowed- use areadonly struct
otherwise a defensive copy is created -
in
=> pass by reference, no property modification allowed - use areadonly struct
otherwise a defensive copy is created
-
-
use
ref struct
definition to garantee that the struct will never be heap allocated
-
-