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 and GetHashCode methods

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 and GetHashCode 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, like String.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
  • 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 than foreach
    • might not have any impact, because of compiler optimizations
    • foreach cannot transformed to for on IEnumerable<T>'s

P/Invoke

Delegates

Exceptions

Dynamic