Thursday, June 18, 2015

Making .NET Applications Faster by Sasha Goldshtein

Any person who does not care about performance of their components is a horrible person. Shun that person like the plague. The seminar focused on three areas for improving performance:
  • Working with collections
  • Improving startup times
  • Reducing GC pressure
For collections running times and space complexity needs to be considered, however internal structure as well as specialized functions must also be taken into account. The basic .NET collections are Array, List and, LinkedList. Arrays are static in size but fast, Lists are dynamic in size but adding elements anywhere else than at the end is costly, a LinkedList in cheap in insertions but requires a lot more memory space which affects performance when going through all elements.

Another collection group is trees; examples are SortedDicitionary and SortedSet which have efficient lookup but they have an even bigger space requirement per item than linke lists. There are also associative collections such as Dicitionary and HashSet which is somewhere in between LinkedList and Arrays in space requirements.

There are use cases when the existing collections does not fit well, for instance finding words that begin with a specific prefix. Structures that handles this kind of scenario are called Tries.

The key point is that for certain scenarios using a custom collection can boost performance.

Startup can be separated in cold startup and warm startup. Cold startups are when the application has not executed since last reboot, this startup time is dominated by disk I/O operations e.g. loading assemblies and similar. For warm starups JIT compiling and similar is the biggest problem

To improve startup time NGen can be used to compile the .NET code to native code which will speed up load times. Another trick is to enabled Multi-Core background JIT by using ProfileOptimization.SetProfileRoot and ProfileOptimizations.StartProfile. Another solution is to use the faster RyuJIT compiler, however it is not released yet so it might not be 100% stable. It will be part of Visual Studio 2015 and .NET Framework 4.6 release.

To improve cold startup all the assemblies can be merged together and this can be done with ILMerge. Another approach is to use .NET Native that compiles everything down to a single native executable. This removes the need to having the .NET Framework installed on the target machine. However .NET Native is only available for Windows Store Apps.

For optimizing GC handling there are many performance metrics:
  • Performance Counters
  • Event Tracing for Windows
  • Memory Dumps
A simple technique to get better performance is to use Value Types where applicable. Value Types are smaller than reference types and are embedded in their containers.

Finally: don’t use finalization.

This has been the absolute best for me so far at the conference

No comments:

Post a Comment