The EQATEC Profiler for .NET

The EQATEC Profiler is an easy-to-use free code profiler for all .NET developers.

Some key features are:

The simple steps of profiling

The EQATEC Profiler is powerful, yet very simple to use. You just point and click a few times:

Profiling an application with EQATEC Profiler

First you select your .NET application, then you build a profiled version, then you run that profiled version, and finally you view the visual report it generates and start looking for bottlenecks.

That's it, really. Read on if you want more details.

Profiling in details

Here we will describe some more details about the three steps of profiling.

Step 1: Build

The Build-tab is where you generate the profiled version of an application. The profiled version will have some additional timing-instructions injected into it.

Building a profiled application with EQATEC Profiler

You can change the default build-options in Tools > Default Profiling Options, or change options just for this one app. All settings for profiling this particular app is stored in the file app.eqconfig in the application's directory.

You can load/save options from other config-files, too, so e.g. various project-members can have each their preferred profiling-options. These can and be put under version-control. Note, that they must, however, reside in the app's folder.

Build options

You will normally not need to change the build options.

Options for profiling an application with EQATEC Profiler
  • Output folder: This is where you profiled app ends up. Change this if e.g. you are not allowed to write to the default output-folder. Note that on e.g Vista you are probably not allowed to write to C:\Program Files, so you must choose a different output-folder if you wish to profile an installed application.
  • Full/CF .NET apps: This is where reports ends up. Change this if you want them to end up somewhere else, e.g. on a network drive or on a memory card.
  • Take snapshots: Do or don't inject code to take automatic profiling-snapshots for these three cases. It's usually harmless to just have all three selected.
  • Tiny methods: Is always best to skip; see "Overhead and performance" further down. Change this if you wish to check that the method is really called (use callcount only for that) or if you simply wish these methods to be reported just like any other method (use full info, but don't place too much trust in the timing numbers).
  • Runtime logging: The runtime-module can print out diagnostics, mostly useful for debugging the profiler itself. You may want to not print anything at all (for e.g. a device with no writeable disk) or print detailed info (for e.g. debugging the profiler).
  • Runtime control: If enabled, an embedded web-service will be running in your profiled app. The profiler can use that to take runtime snapshots. You may want to disable this if your app is not allowed to listen on service ports at all. Change the port, if the default choice does not suit you, or if you want to run two different profiled apps on one machine at the same time, e.g. in a client/server scenario.

For folders you may use environment variables in the settings, e.g. $(SystemRoot). One special pseudo-variable has been added: $(AppDir) is the path to the unprofiled application itself.

One special use of $(AppDir): you can set the output-folder to $(AppDir), which means that the profiled app will end up in the same folder as the original. This can sometimes be handy, e.g. in an automated autobuild-scenario, but do note that the originals will be overwritten so you will have to rebuild them again if you ever want to re-profile the app.

Step 2: Run

The Run-tab is where you run and control a profiled application.

Run and control a profiled application with EQATEC Profiler
  • Note: Your FIREWALL might popup a notice the first time you run any new profiled app, alerting you to the fact that the profiled wants to open a service on a port. Do not be alarmed, because that is okay: that service is how you can control the app and take live snapshots.
  • To connect to a running profiled app simply enter a DNS-name or IP-address; the profiler will connect automatically.
  • "Take snapshot" will generate a profiling-report and reset all method's timing counters to 0, while "Reset counters" will only reset the timing counters.
  • If the profiler is connected to a .NET CF app that is writing a report, the report will be transferred into your "full .NET report-folder" and deleted on the device afterwards.
  • Command-line args and preferred host are remembered in the registry on a per-app basis.

Yes, but what about Compact Framework apps, or .NET services, or ... ?

The profiler can only run an executable from the output-directory. That is fine for full .NET Windows applications, but not for other types of executables. And unfortunately, you may still have to deploy and run them manually yourself:

  • Compact Framework apps: you must manually copy the profiled app onto your device/PDA and run it there.
  • .NET service: you must manually stop the existing service, install/copy the profiled version, and restart it.
  • ASP.NET: you must manually copy the output files to the destination.

(We say "may" because you might be able to automate this step by specifying an output-path that copies the files to the right place.)

Note that it is only the deployment/copying-step and starting that must be done manually; once the app has been started you can control it and get reports just like for a ordinary standalone full .NET app.

Step 3: View

In the View-tab you view a profiling-report and hopefully find the app's bottlenecks.

You can browse the executed methods by selecting them in the upper list or in the lower call-graph view. Just follow the highest total time to find performance bottlenecks.

View a profiling report generated by the EQATEC Profiler
  • The upper summary show the grand total for each method: how many times it was called during this run and how long that took.
  • The lower call graph show the details of the selected method. The neighbor columns, "called by" and "called into", will show numbers related to the particular calls into and from the selected method.
  • The yellow bars show how much time each caller spends calling the selected method. Some caller's calls may be cheap while others are expensive. All the yellow bars add up to 100%.
  • The red bars show how much time is spent internally in the selected method and by the methods it calls. Those figures add up to 100%.
  • If a method is still running its timing will be shown with a '+' in front of it. This only happens if you take snapshots for a live application. What it means is that currently the reported internal execution time may be too low, as the latest call to the method has not yet completed.
  • If a method is recursive a '<' is shown in front of it. In the current version the sum of a recursive method's calls is nearly always too high. This is rather tricky problem to solve for any profiler.
  • Navigate backwards/forwards in the call-graph. The entire background acts as a back/forward-button, making it really easy to hit. Note that selecting a different method in the summary-view resets the "history".

Overhead and performance

We have found that a profiled application typically is 30% larger than the original and runs 30% slower. However, this can vary a lot and "the overhead" is of course much more complex. Here is the full story. Knowing this can help you understand certain profiling-situations.

The code-overhead of a profiled app consists of two parts:

  • Base runtime-module: fixed overhead of about 60 Kb.
  • Per-method overhead: instrumenting a profiled method typically adds 40 bytes, and storing its name also adds some bytes, like 10-20% of the name's length in bytes (method-names are stored compressed).

A small app will therefore grow very much, maybe several hundred percent, due to the added 60Kb. On the bright side an app may also shrink in size, because instrumentation optimizes branching in the existing code.

The runtime-overhead of timing a profiled method typically requires executing an additional 80 CIL assembly-instructions. That is why it is highly recommended that tiny methods (simple set/get of variables, 3-8 CIL instructions long) should not be profiled. It hardly makes sense to spend 10-20 times as much time timing a method than just executing it.

This means that a computing-intensive app, or an app calling a lot of small, profiled methods, can run very, very slow. Several orders of magnitude slower, in fact. A profiled fractal-generator app might run 5 times slower when profiled. On the other hand, many regular apps we have tested have run with only a slight hint of overhead during "normal use", so this is indeed an area of great variation.

Profiler API

If your application includes a reference to the runtime-module it may programmatically control certain profiling aspects. A generic version of the runtime-module is included in the installation (...\RuntimeDLL\EQATECProfilerRuntime.dll) specifically for the purpose of being used as a reference. You will most likely want to copy that DLL to your project and place it under version control, if you use it.

The programming API allow you to take snapshots at runtime, clear the counters, examine the profiling-settings etc. Please explore EQATEC.Profiler.Runtime for the full API. Here is an example:

Use the runtime-API to dump snapshots at will

You may also add attributes to prevent methods from being profiled or appearing in the runtime-report. Profiled apps normally run fast enough, but it's there if you really need it:

Use attributes for finer profiling-control

"HideAtRuntime" means that this method's activities will not be reported at runtime. "SkipInstrumentation" avoids profiling this method entirely. If you specify the attribute for an class it takes effect on every method in that class.

Known limitations

This is a list of known limitations and problems in version 2.0.

  • Blocking methods, such as Read(), will be counted as the total time, including the time the thread spends being descheduled and waiting for the call to complete. For now, you will have to recognize and judge situations like this manually.
  • No debug information is available for the profiled assemblies. It means that you cannot debug the profiled versions - but you would probably not like to do that, anyway.
  • No Visual Studio integration yet. We are looking into providing an add-in that will make it even easier to enable profiling your solution's assembly files.
  • No full method signature is displayed yet. So if you have several overloaded methods by the same name, or use generic methods, you cannot easily distinguish them as their signature (the method's parameter list) is not displayed anywhere.
  • Only defined methods are currently profiled, not referenced ones. So all the methods that your application itself defines will be profiled, but not System.* etc.

Contact

The EQATEC Profiler is a work in progress. Your input is most welcome: if you have any problems or suggestions then please let us know.

Visit our forum at http://www.eqatec.com/forum
Send us an email at [email protected]

Best regards,
the EQATEC tools team