Benutzer:MovGP0/Performance/Coding
aus Wikipedia, der freien Enzyklopädie
Coding and Class Design
Class
- passing is cheap, because only pointer is copied
- base class and pointer has overhead
- 32 bit system: 12 byte + 4 byte pointer
- 64 bit system: 24 byte + pointer
- overhead causes more garbage collections
- default implementation of
==
and!=
only check for reference equality- may not need override of
Equals
andGetHashCode
methods
- may not need override of
Struct
- no overhead
- no garbage on the heap
- copied on every use by a function
- need to be small
- array of structs is accessed very fast
- CPU cache stores whole segment of the array
- no need to resolve pointers and retrieve data from RAM
- needs to be considered special for updates
- prefer them to be read-only
- use to refactor part of a class into a separate structure
- override
Equals
andGetHashCode
methods- default implementation uses reflection
- implement
IEquatable<T>
too - implement
==
and!=
operators
Evil | Correct |
---|---|
struct Point
{
public int X;
public int Y;
}
public static void Main()
{
var points = new List<Point>();
points.Add(new Point() { x = 1, y = 2 });
points[0].X = 3; // BUG: point is not modified, but only a copy of it
}
|
struct Point
{
public int X;
public int Y;
}
public static void Main()
{
var points = new List<Point>();
points.Add(new Point() { x = 1, y = 2 });
var point = points[0];
point.X = 3;
points[0] = point;
}
|
Virtual Methods
- do not mark methods
virtual
by default- prevents JIT optimizations, like inlining
- use virtual when reusability is more important than performance
Sealed Classes
- future JIT performance optimizations possible
- make classes sealed by default
Avoid Interface dispatch
- first call on a method from an interface requires object type lookup
- if its always the same type, the CLR will optimize
- creates a "monomorphic stub"
- monomorphic stub gets replaced when the type changes
- having multiple types in an array with a given interface creates a "polymorphic stub"
- hashtable to monomorphic stubs for the given types
- avoid interfaces when not needed
- prefer an abstract base class when single inheritance applies
Avoid Boxing
- costs time for allocation, copying and casting
- puts GC pressure on heap
- easy identifyable in ILSASM because of the
[box]
keyword - when boxing is unavoidable, a class is prefered over a struct
- Causes
- assigning a primitive to an object
- functions that take
object[]
as parameter, likeString.Format
- casting a struct to an interface, which the struct implements
- Bugs
- boxed value/struct is a copy of the original
- changing the value of the original will not change the boxed value
Casting
- avoid Casting when possible
- avoid
InvalidCastException
!!!- use
as
instead
- use
- avoid
- cost depends on hierarchy
- casting to parent is cheap
- casting to child is expensive
- cost increases with depth of hierarchy
- casting to an interface is more expensive than casting to an concrete type
Evil | Good |
---|---|
Foo f;
if(a is Foo)
{
f = (Foo)a;
}
|
Foo f = a as Foo;
if(f != null)
{
// ...
}
|
For and Foreach loops
for
loops are faster thanforeach
- might not have any impact, because of compiler optimizations
foreach
cannot transformed tofor
onIEnumerable<T>
's