Appendix A—Kick-Start Your Application’s Performance

This book goes through hundreds of details that may be a problem in your application, but if you are just getting started, here is a general outline of how you can proceed and analyze your own program’s performance.

  1. Define Metrics

Before starting, you need to define the types of metrics that you analyze. Is it just pure CPU usage? Memory? Speed of operations? Define these in as much detail as possible. Come up with a set of detailed goals for each metric.

  1. Analyze CPU Usage
  • Use PerfView or VS Standalone Profiler to get a CPU profile of your application doing work.
  • Analyze the stacks for functions that stand out.
  • Is data processing taking a long time?
  • Can you change your data structure to be in a format that requires less processing? For example, instead of parsing XML, use a simple binary serialization format.
  • Are there alternate APIs?
  • Can you parallelize the work with Tasks or Parallel.For?
  1. Analyze Memory Usage
  • Consider the right type of GC:
  • Server: Your program is the only significant application on the machine and needs the lowest possible latency for GCs.
  • Workstation: You have a UI or share the machine with other important process.
  • Profile memory with PerfView:
  • Check results for top allocators—are they expected and acceptable?
  • Pay close attention to the Large Object allocations.
  • If gen 2 GCs happen too often:
  • Are there a lot of LOH allocations? Remove or pool these objects.
  • Is object promotion high? Reduce object lifetime so that lower generation GCs can collect them. Allocate objects only when needed and null them out when no longer needed.
  • If objects are living too long, pool them.
  • If gen 2 GCs take too long:
  • Consider using GC notifications to get a signal when GC is about to start. Use this opportunity to stop processing.
  • If you have high number of gen 0/1 GCs:
  • Look at highest area of allocations in the profile. Find ways to reduce the need for memory allocations.
  • Minimize object lifetime.
  • If gen 0/1 GCs have a high pause time:
  • Reduce allocations overall.
  • Minimize object lifetime.
  • Are objects being pinned? Remove these if possible, or reduce the scope of the pinning.
  • Reduce object complexity by removing references between objects.
  • If the LOH is growing large:
  • Check for fragmentation with Windbg or CLR Profiler.
  • Compact the LOH heap periodically.
  • Check for object pools with unbounded growth.
  1. Analyze JIT
  • If your startup time is long:
  • Is it because of JIT? Loading data is a more common cause of long startup times.
  • Use PerfView to analyze which methods take a long time to JIT.
  • Use Profile Optimization to speed up JIT on application load.
  • Consider using NGEN.
  • Are there methods showing up in the profile that you would expect to be inlined?
  • Look at methods for inlining blockers such as loops, exception handling, recursion or more.
  1. Analyze Asynchronous Performance
  • Use PerfView to determine if there are a high number of contentions.
  • Remove contentions by restructuring the code to need fewer locks.
  • Use Interlocked methods or hybrid locks where necessary.
  • Capture Thread Time events with PerfView to see where time is being spent. Analyze these areas of the code to ensure that threads are not blocking on I/O.
  • You may have to significantly change your program to be more asynchronous at every level to avoid waiting on Tasks or I/O.
  • Ensure you are using asynchronous stream APIs.
  • Does your program take a while before it starts using the thread pool efficiently? This can manifest itself as initial slowness that goes away within a few minutes.
  • Make sure the minimum thread pool size is adequate for your workload.

 

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
13.59.32.1