Home » 2.5. DW Performance

2.5. DW Performance

Selected References:

  • Writing High Performance .NET Code – Ben Watson – 2014 ( writinghighperf.net )
  • Ultra-Fast ASP.NET 4.5 – Richard Keissig – Apress – 2012 ( 12titans.net )

Performance and Efficiency

** Important note:  The performance and efficiency described in this documentation refer to the software executables (.exe’s) running in the system.  This includes the .exe’s of the processing nodes, native client applications, and so on.

The performance of an executable will generally come down to some type of count per period of time.  Transactions per second, pages per second, throughput per second, and so on.  A higher performance number is always better.  The efficiency of an executable measures the amount of resources used while performing realistic workloads.  CPU percentage used, amount of memory used, amount of network bandwidth used, etc.  A lower efficiency number is always better.  When measuring performance and efficiency, it is important to keep in mind that there are no absolute standards.  The data collected can only be assessed relative to an application’s own changing metrics over time or compared to data from other applications measured at a given point in time.  It is very important that the data collected during these measurements be stored and saved for future analysis.

Increasing the performance and efficiency of .NET managed executables is difficult to generalize, but there are some guidelines that work in almost all cases.  Most of them involve finding ways to work with the garbage collector rather than against it, while also using the most efficient alternatives in the .NET framework to accomplish each task.

  • Minimize allocations of memory (object instantiation).  In practice, this means that the object model for a system must be as small and flat as possible.
  • Try to only instantiate objects that are less than 85K in size so they are created in the Gen 0 memory segment of the managed heap. Objects larger than 85K are automatically created on the Large Object Heap.
  • Minimize the lifetime of objects so that they go out of scope before the next collection, which avoids promoting objects to a higher generation. Gen 0 collections are relatively fast and efficient.  Gen 2 is a full collection (all generations plus the LOH), which is a very heavy and expensive process.
  • Large or long-lived objects should be pooled in order to be reused. Doing so can prevent the need for a full Gen 2 collection.
  • Avoid the use of .NET features that are composed of layers of abstraction over lower-level functionality, intended to simplify the work of the developer.  Use the lower-level functionality directly, bypassing the abstractions that add bloat to the executable.
  • Avoid the use of dynamic code.
  • Avoid the use of generated code.

The second general objective is to tailor your code to maximize the optimizations performed by the JIT compiler when creating the executable.  In practice, this basically entails avoiding certain parts of .NET that quite literally prevent JIT optimizations (some examples are listed in the next section).

In summary, the key to producing high performance .NET applications and systems is to focus on the measurement of the performance and efficiency of the compiled executable.   Once that has been accomplished, you then work backward using those measurements to tailor your system architecture and code implementation to adapt to the strengths of the garbage collector and JIT compiler while avoiding their respective weaknesses.  The payoff for doing so is to enjoy all of the developer productivity and benefits of managed code, while at the same time producing executables equivalent to those of native C++ in terms of performance (and to a lesser degree efficiency).  The Bing search engine is a good example of the results of these types of .NET optimizations in action.

 

Web Service API Optimizations

  1. IIS
    • Disable compression (if handled by API compression/encryption)
    • Enable and tune HTTP keep-alive
    • Multiple worker processes as web garden (depends on CPU utilization)
    • Tune IIS/ASP.NET thread pools (default values for now)
    • Separate AppPool per owner/tenant
    • Avoid server-side session state (single point of failure and performance bottleneck)
  2. Stateless web service API’s for best performance and scalability
    • Minimize number of calls made by client applications to the web service API’s
      • Batching of multiple API methods per single request
      • Return of multiple results per API method call
  3. Reusable code libraries
    • Minimize object lifetimes
      • Create objects just before they are needed
      • Assign objects to null as soon as they are no longer needed (position of braces does not help)
    • Minimize memory allocations (object instantiation) as much as possible
      • reducing the number of classes in the object model
      • increasing the lines of code per method in each class
    • Minimize blocking calls made to I/O or RPC’s
      • NOTE 1: version 4.5.1 ASP.NET web services do not support tasks/threading due to the fact that IIS can terminate its worker thread at any time.  Version 4.5.2 and later will force IIS to wait for the tasks/threads to complete before terminating a worker thread
      • NOTE 2: MySql 5.7 and Connetor/Net do not yet support asynchronous calls to the database (the async versions of methods do not actually work).  If/when support is added for async/await, the request message pipeline will have to be rewritten to be asynchronous from start to finish.
      • As a result of these limitations, the primary mechanism to reduce idle threads due to blocking synchronous RPC’s is to use SSD’s to significantly decrease the latency of such calls.
    • Keep the object model as flat as possible and reduce references between objects in order to reduce tree depth and simplify collections
    • Collect objects in Gen 0 by keeping the size of objects below 85K along with minimizing the object lifetime
    • Avoid the use of .NET functionality that prevents compiler optimization, such as virtual methods, recursion, or Interface Dispatch
    • Avoid the use of .NET functionality that is computationally expensive and/or inefficient, such as reflection, LINQ, regex, boxing, P/Invoke
    • Limit the use of casting as much as possible
  4. Data access logic
    • Avoid code generators, such as the Entity Framework, in favor of using ADO.NET directly
  5. Logging and Metrics
    • Reserve standard logging for errors and exceptions (Serilog)
    • Use the tools listed below to manually measure all relevant aspects of your systems and executables
    • Create a subsystem to record the ETW metrics that are indicative of the performance and efficiency of the system, and store those metrics in some way so they can be analyzed periodically for comparison purposes.  ETW metrics are so lightweight they can be used on production systems

 

 

Web Application Optimizations

Unlike native applications or web services, web applications are a special case since the logic can run entirely on the server, or entirely in the browser (JavaScript), or some combination of the two.  Google’s Ilya Grigorik (top two links above) sums it up the best:

<html>
<head>

<style>
.main { … }
.leftnav { … }
/* … any other styles needed for the initial render here … */
</style>

<script>
// Any script needed for initial render here.
// Ideally, there should be no JS needed for the initial render
</script>

</head>
<body>
<div class=”main”>
Here is my content.
</div>
<div class=”leftnav”>
Perhaps there is a left nav bar here.
</div>

<script>
function run_after_onload() {
load(‘stylesheet’, ‘remainder.css’)
load(‘javascript’, ‘remainder.js’)
}
</script>

</body>
</html>

  • Inline CSS needed to render the page “above the fold”
  • Only send HTML to the browser, with clean DOM and CSSOM rendering paths (no blocking on JavaScript, etc.)
  • Load non-essential resources at the bottom of the body, after the page has been rendered.
  • The goal is for each page to essentially be a single HTTP request with everything needed to render the page inline.
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: