Writing High Performance .NET Code


Since most day to day operations are moving online (Core banking, Reservations, Shopping), software performance has become vital to their success. So many a times visits to a web site takes long time to load, resulting in frustration and the migration to a different site (similar business). For businesses this can be fatal as they lose customers. Web sites often slow or even go down when traffic increases. Performance/stress testing of your application can help avoid such downtime. There are tools that tell you performance of your application is bad but not necessarily why. But if you have information knowing what to look for, what is good and what is bad, will put your application in better shape later.

Performance/stress testing of your application can help avoid such downtime.

With Microsoft® .NET Framework, developers can now build complete business solutions quickly with more functionality and robustness with its rich and easy to use features and functionality. But with this comes increased opportunity for architects and developers to design and build poor, non scalable solutions because architecting and designing these solutions are not really very straight forward. This paper talks about the core performance related issues that one should be aware of in .NET. It also focuses on some common mistakes which one should avoid and provider few tips for writing high performance .NET code.

This paper will discuss:

  • .NET Framework components and CLR execution Model

  • Threading support in .NET and tips for avoiding common threading mistakes

  • Automatic Memory management – Writing GC friendly code

  • Briefly talks about performance tools available for tuning .NET code

The .NET Framework provides a run-time environment called the CLR, which manages the execution of code and provides services that make the development process easier. CLR provides features such as automatic memory management (GC), exception handing, security, type safety, JIT (Just in time compiler for converting msil to native code) and more. CLR is implemented as a dll called "mscorwks.dll". It also has support for Base Class Libraries (BCL) which sits on top of CLR, providing libraries for functionalities such as String, File I/O, and Networking, Collection classes, Data Access (ADO.NET) and XML processing. On top of BCL there are presentation layers (Web Forms and Windows forms), which provide UI functionality. Last, one finds the languages that Microsoft ® provides for .NET. Currently there are more than 15 different languages that are targeted for .NET framework.

CLR Execution Model:

Each Language has a compiler which compiles and converts the code to msil (Microsoft® Intermediate Language). There are multiple optimizations that are built into each of these compilers which produce efficient IL code. Then CLR takes over and it has the JIT compiler convert this IL code into native code that CLR can execute. The JIT compiler also has many optimizations built in which can produce efficient native code for better performance. If the code is unmanaged, then we bypass most of this and can directly run unmanaged programs. Note that .NET provides additional features by which we can use pointers to access arrays etc through a feature called "unsafe" for better performance Read More

Threading support in .NET and tips for avoiding common threading mistakes

Threading support in .NET is implemented in System.Threading namespace. This provides the classes and functions such as creating/destroying threads, synchronization primitives for atomic access that needed to write multi threaded code. This namespace also provides a class that allows us to use the pool of system provided threads called "Threadpool".

So how does the formula work?

The number of worker threads = maxWorkerThreads*# of CPU (Cores) in the system – minFreeThreads 16 = 12*4-32 (assuming you are running a 4 core machine). The total number of concurrent requests you can process is 16. But an interesting question arises. How do you know that this actually worked? Look at the "Pipeline Instance Count" performance counter and it should be equal to 16. Only 1 worker thread can run in a pipeline instance count so you should see a value of 16. You have to be very careful when doing this as performance may degrade if you use random values

.NET threading APIs and Thread pool make a developers life easier, but still there are many threading related issues that can hurt performance and scalability. Creating more or fewer number of threads than required can impact performance. Use Thread pool to help you in this instance. Ideally, the number of threads will equal the number of cores, and will yield the highest performance as each thread that can run concurrently on a processor. Threading wrong portion of application: This is by far the major problem in threading. Analyze your application completely before deciding where to thread. You have to thread the portion of your code where you spend most time to get significant performance. Multi threading also complicates debugging and events such as dead locks and race conditions. Have a good debug log (that you can enable in debug mode) to solve some of these complex nature bugs.

Threading Tips:

  • Distribute the work equally among threads – If the work is imbalanced, one thread will finish the work quickly, but must wait till other thread(s) finish their job, impacting performance.

  • Dont use too much shared data among threads – If any data or data structure is shared among threads, then synchronization is required to update that data. This increases the amount of serial code/paths in your application hurting your scalability

  • Acquire Lock late and release it early. This is very important as you must take a lock just before you absolutely have to and release it first before doing anything once the atomic region is executed. Here is an example in .NET

--Milind P Hachinmani, is currently a Senior Application Engineer with 13 years of industry experience with over 7+ years @ Intel. He joined APAC enabling team last year and has been working with Enterprise ISV s and SI s to improve their application performance on Intel® Architecture. At Intel, in his previous role for 6 years Milind worked as a member of the Intel on-site team at Microsoft in driving improvements in the quality and performance of three generations of Microsoft® .NET Framework for Intel Architecture. His expertise includes performances methodologies, benchmarking and .NET CLR internal