The EQATEC Profiler for .NET
The EQATEC Profiler is an easy-to-use free code profiler for all .NET developers.
Some key features are:
- Code-profile any .NET 2.0 and above application
- Code-profile .NET Compact Framework applications, too; no other can do this
- Use as stand-alone GUI profiler or profile from the command-line
- Use precise instrumentation to present an easy-to-navigate full method-call graph
The simple steps of profiling
The EQATEC Profiler is powerful, yet very simple to use. You just point and click a few times:
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.
- Browse to, or simply drag-drop a folder on this tab, to select an application.
- Press shift-delete to remove an app from the "most recently used" drop-down list.
- Normally you will always want to include (profile) all the application's assembly-files.
- Building a profiled version will copy all files in the app-folder recursively into a completely new neighbor-folder, named "dir-Profiled" by default.
- If you wish to profile a signed assembly you must re-sign it afterwards. Alternatives are skip (don't profile this assembly) or strip (don't resign, which will likely cause trouble).
- You can control snapshot and method-profiling programatically, too. See "Profiler API" further down.
- A command-line version, EQATECProfilerCmd, is available in the registered version. Use it to build a profiled version in e.g. your autobuild.
- If more that one executable is found you must manually move to the Run-tab and select which one to run. If only one exe is profiled you can use the yellow Run-button to do that.
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.
- 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.
- 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.
- 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:
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:
"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