Ahieving Performance C#


Published on

Short presentation containing tips and tricks on how to make C# apps to perform very well.

Published in: Technology
  • Be the first to comment

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

Ahieving Performance C#

  1. 1. AchievingPerformance in C# Roman Atachiants
  2. 2. Contents• Introduction• Memory Management• Flow and Control Structures• Data Structures• Function Calls• Questions
  3. 3. Introduction“Premature optimization is the root of all evil” Prof. Donald Knuth
  4. 4. Software• Correct• Maintainable• Fast
  5. 5. When & Where• One should not optimize everything prematurely• One should keep in mind good programming practices• One should evaluate the
  6. 6. The SecretNot to do ANY work.
  7. 7. Memory Management“The memory management on PowerPC can be used to frighten small children” Linus Torvalds
  8. 8. GC• The .NET Framework uses automatic garbage collection to manage memory for all applications. Memory for an Object’s object is memory is freed allocated from (collected) the managed some time later heap when you call new Object dies tu to all its references Object either being constructor is explicitly set to called null or going out of scope Object is used for some time
  9. 9. Assemblies• Prefer single large assemblies rather than multiple smaller assemblies• Overhead: o The cost of loading metadata for smaller assemblies o Touching various memory pages in pre-compiled images in the CLR in order to load the assembly (Ngen) o JIT compile time o Security checks• Sometimes you cannot avoid splitting assemblies; for example, for versioning and deployment reasons. If you need to ship types separately, you may need separate assemblies.
  10. 10. Memory• Allocation: o Is super fast!• Free: o Is super slow!• You want to avoid freeing memory. The easiest way to do so is not to allocate in the first place.
  11. 11. Reuse Memory • Do not use a new in a loopfor (int i = 0; i < 100; ++i) unless you really need to.{ var numbers = new int[10]; // (...) Do something with numbers Console.WriteLine(numbers.Sum());}var numbers = new int[10];for (int i = 0; i < 100; ++i){ // (...) Do something with numbers Console.WriteLine(numbers.Sum());}
  12. 12. Object Poolspublic sealed class ScriptBuilder : RecyclableObject • Object Pooling is{ ... something that tries to} keep a pool of objects inpublic sealed class ScriptBuilderPool : memory to be re-usedConcurrentPool<ScriptBuilder>{ later and hence it will public static readonly ScriptBuilderPool Default = new ScriptBuilderPool(); reduce the load of object public ScriptBuilderPool() : creation to a great extent base("ScriptBuilders", _ => new ScriptBuilder()){ }} • Object Pool is nothing butusing (var obj = ScriptBuilderPool.Default.Acquire()) a container of objects{ // Do stuff that are ready for use}
  13. 13. Class Design• Do not make classes thread safe by default.• Consider using the sealed keyword.• Consider the tradeoffs of virtual members.• Consider using overloaded methods.• Consider overriding the Equals method for value types.• Know the cost of accessing a property.• Consider private vs. public member variables.• Limit the use of volatile fields.
  14. 14. Class vs Struct• Class o A reference type o Lives in the heap o Slower• Struct o A value type o Lives in the stack o Faster• … But, never use structs that are bigger than 16 bytes. Use them wisely.
  15. 15. Threads• Thread threads as a shared resource o Do not create threads on a per-request basis because this can severely impact scalability. Creating new threads is also a fairly expensive operation that should be minimized. Treat threads as a shared resource and use the optimized .NET thread pool.• Locking is slow, avoid locking large portions of code• Minimize thread creation• Use the thread pool when you need threads• Use a timer to schedule periodic tasks• Never use Thread.Abort• Never use Thread.Suspend or Thread.Resume
  16. 16. Flow & Control “It is practically impossible to teach good programming style to studentsthat have had prior exposure to BASIC. As potential programmers, they are mentally mutilated beyond hope of regeneration.” E. W. Dijkstra
  17. 17. For vs For..Each • For and for .. each loopsforeach(var item in List) are different:{ o For each is less performant than a // do something with item for loop} o For each creates garbageint count = List.Length; • Always prefer for loops forfor(int i=0; i < count; ++i){ critical code var item = List[i]; // do something with item • Any idea why?}
  18. 18. Switch vs If Matching Non- • A switch statement Matching compiles to a different set of instructions andSwitch 15,7 sec 0,0 sec optimized for fast state-Statement machines.If 20,7 sec 0,1 secStatement • Because each case within a switch statement does not rely on earlier cases, the compiler is able to re-order the testing in such a way as to provide the fastest execution.Reference: http://www.blackwasp.co.uk/SpeedTestIfElseSwitch_2.aspx
  19. 19. Exceptions for (int i=0; i < 5000000; i++) • When an exception is { thrown, your application dies try { a little bit throw new ApplicationException(); } • Never throw exceptions in catch (ApplicationException) order to control the flow of { } the application } • However, do not use error codes because of concerns that exceptions might affectTotal time taken: 00:00:42.0312500 performance negativelyExceptions per millisecond: 118 • Consider using TryParse() patternReference: http://www.developerfusion.com/article/5250/exceptions-and-performance-in-net/
  20. 20. Data Structures“Most software today is very much like an Egyptian pyramid with millions of bricks piled on top of each other, with no structural integrity, but just done by brute force and thousands of slaves.” Alan Kay
  21. 21. Stringsstring BadConcatenate(string[] items) • C# strings are immutable string strRet = string.Empty; foreach(string item in items) • Prefer String.Concat() to { strRet += item; String.Format() } return strRet; • StringBuilder is the only} way to have mutablestring GoodConcatenate(string[] items) strings, but still creates{ var builder = new StringBuilder(); some garbage. foreach(string item in items) { builder.Append(item); } return builder.ToString();}
  22. 22. Collections• Use the right type of the collection for your work• Stop using List<T> for everything• Ask yourself: o Do you need to sort your collection? o Do you need to search your collection? o Do you need to access each element by index? o Do you need a custom collection?
  23. 23. Collections• Use the right type of the collection for your work• Stop using List<T> for everything• Ask yourself: o Do you need to sort your collection? • List<T> to bind read-only sorted data • NameValueCollection for sorting strings • SortedList<K,V> presorts while constructing o Do you need to search your collection? • Use Dictionary<K, V> o Do you need to access each element by index? • Use List<T>, Dictionary<K,V>, SortedList<K,V> o Do you need a custom collection? • Ask me, you probably don’t need it.
  24. 24. Arrays// 2D array of 100 x 100 elements.for (int a = 0; a < 100; a++) • Multidimensional Arrays [,]{ for (int x = 0; x < 100; x++) are slow. { int c = a1[a, x]; • Prefer jagged [][] arrays.} } • Arrays have a static size. The size of the array// Jagged array of 100 x 100elements. remains fixed after initialfor (int a = 0; a < 100; a++){ allocation. for (int x = 0; x < 100; x++) { int c = a2[a][x]; 2D array looping: 4571 ms } Jagged array looping: 2864 ms [faster]} Reference: http://www.dotnetperls.com/regex-performance
  25. 25. RegExstatic Regex wordRegex = new • A regular expression isRegex(@"W+", RegexOptions.Compiled); essentially a state machinestatic void Main(){ • Always use string s = "This is a simple /string/for Regex."; RegexOptions.Compiled if string[] c = wordRegex.Split(s); you plan to reuse a regular foreach (string m in c) { expression Console.WriteLine(m); } • RegexOptions.Compiled} takes 10x longer to startup, but yields 30% better runtime. Reference: http://www.dotnetperls.com/regex-performance
  26. 26. Functions“Controlling complexity is the essence of computer programming” Brian Kernighan
  27. 27. Inline • You want the compiler to inline methodspublic class MyClass{ protected virtual void SomeMethod() • Mark them as sealed { ... }} • This code ends the chainpublic class DerivedClass : MyClass { of virtual overrides and protected override sealed void makes DerivedClass. SomeMethod () { ... }} SomeMethod a candidate for inlining
  28. 28. Copying Buffersint[] arr1 = new int[] { 1, 2, 3, 4, 5 };int[] arr2 = new int[10]; • Never copy buffers with a// Copy the first twenty bytes from loop, preferarr1 to arr2 Buffer.BlockCopy() orBuffer.BlockCopy(arr1, 0, arr2, 0, 5 * sizeof(int) Array.Copy());
  29. 29. Recursionprivate void RecursiveDir(string currentDir){ • Avoid recursion foreach (var sin Directory.GetDirectories(dir)) RecursiveDir(s); • Most of the foreach (var file in Directory.GetFiles(dir)) Console.WriteLine(file); recursion can be} converted to a tail-private void IterativeDir(string startingDir) recursion{ Stack stackFrame = new Stack(); • A tail-recursion is a stackFrame.Push(startingDir); while (stackFrame.Count > 0) simple loop { var current = (string) stackFrame.Pop(); foreach (var sin Directory.GetDirectories(current )) stackFrame.Push(s); foreach (var file in Directory.GetFiles(current)) Console.WriteLine(file); }}
  30. 30. More Tips (1)• LINQ is slow, never use it if you need performance• Never use reflection if you need performance• Keep IO Buffer Size Between 4KB and 8KB• Always use Asynchronous IO (Uses IOCP on Windows)• ASP.NET: cache aggressively• ASP.NET: use session state only if you need to• ASP.NET: remove unnecessary HttpModules• Experiment!
  31. 31. More Tips (2)• Reduce boundary crossings (Unmanaged/Managed, Cross Process, Cross AppDomain)• Prefer single large assemblies• Never use GC.Collect() unless you know what you are doing• Do not implement Finalize unless required
  32. 32. Questions?Thank you for your attention!