CLR Profiler

CLR Profiler is Obsolete

The CLR Profier was a common way to measure memory usage for games. It is no longer maintained by Microsoft and now memory profiling is performed through Visual Studio. This document is kept here for older games which may still benefit from its usage if they are still on .NET Framework 4.X.

Introduction

The CLR Profiler (CLR meaning Common Language Runtime) is a program created by Microsoft which gives detailed information about memory allocation and method calls. It is an invaluable tool for identifying areas of code which allocate too much memory. The CLR Profiler can give you information about where your project is allocating memory, which is the first step in cleaning up the allocation. Memory allocation can cause performance problems because the allocation increases the frequency in which the garbage collector runs. The best way to prevent the garbage collector from running (or to reduce its impact) is to reduce memory allocations. Fewer allocations means that ram needs to be "cleaned" less frequently, so the user will not experience as many pops in frame rate as the garbage collector freezes execution.

CLR Profiler vs. Visual Studio Profiler

Visual Studio 2015 and later includes a built-in profiler which can help you diagnose performance and memory problems. To measure memory allocations in Visual Studio, the profiler can take snapshots of the heap which can be compared to see what allocation is happening in a call. While this is useful if you suspect that a particular call is allocating memory, snapshots are not as useful when measuring memory allocation across multiple frames in a game. Therefore, even though the CLR Profiler is no longer maintained at the time of this writing, it is still a very valuable tool for improving your game's performance, and it can provide more insight into allocations compared to the Visual Studio memory profiler.

What problems can too much memory allocation cause?

The allocation of memory itself isn't necessarily the problem. The problem is the clean-up (called garbage collection) that is triggered due to allocations. The .NET framework provides extremely fast memory allocation due to the way it eliminates memory fragmentation. However, the clean-up of unused objects is another story. During the time of garbage collection (at least as of the .NET Framework 3.5) the program execution must stop. Garbage collection can take enough time that your game will experience a noticeable stop in execution. This "pop" can disrupt game play and appear annoying to the user. Since suppressing the garbage collector is not an option, the solution is to eliminate or reduce memory allocation. Less memory allocation means less frequent cleanup by the garbage collector. Memory can be reduced enough that the garbage collector can run very infrequently. This, coupled with intelligent forced garbage collections by Screens can essentially eliminate pops in frame rate.

Installing the CLR Profiler

To install the CLR Profiler:

  1. Unzip the CLRProfiler45Binaries.zip file

  2. It is recommended that you leave the default unzip folder c:\CLRProfiler

  3. Open the 64 or 32 folders depending on whether your application is 64 or 32 bit. At the time of this writing all FRB apps default to 32 bit.

  4. Double-click CLRProfiler.exe to run the CLR Profiler.

If you get a "Waiting for application to start common language runtime" message in Vista, try running the CLR Profiler as an administrator.

Creating a Sample Program

One of the best ways to test out the CLR Profiler is to use it on an application that you have written. That makes the results a little easier to understand because you can compare the CLR Profiler's log to the code that you've written. To create a sample program, create a new project using a FlatRedBall template, then add the following code: Add the following at class scope:

SpriteList mSpriteList = new SpriteList();

Add the following to Update:

 // Create a Sprite every frame
 Sprite sprite = SpriteManager.AddSprite("redball.bmp");
 sprite.XVelocity = -10 + (float)FlatRedBallServices.Random.NextDouble() * 20;
 sprite.YVelocity = 3;
 sprite.YAcceleration = -4;
 mSpriteList.Add(sprite);

 // See if we need to remove any Sprites.  Use a reverse for-loop
 for(int i = mSpriteList.Count - 1; i > -1; i--)
 {
     const float yToRemoveAt = -15;
     if(mSpriteList[i].Y < yToRemoveAt)
     {
         SpriteManager.RemoveSprite(mSpriteList[i]);
     }
 }

Profiling the demo

The CLR Profiler can now be used to test the application that you've created. To test the application:

  1. Open the CLR Profiler.

  2. Make sure Calls is unchecked (we'll only look at memory allocations in this tutorial)

  3. Make sure Allocations is checked. This must be checked before the program starts (it seems to be a bug)

  4. Optionally - uncheck Profiling active, so you can check it later exactly when you want profiling to start

  5. Click Start Desktop App...

  6. Navigate to the folder where your .exe was built.

  7. Select your .exe and click the "Open" button. If Profiling active is checked profiling will begin immediately. Otherwise, navigate to where you want the profiling to start, then check Profiling active.

  8. Let your application run for a few seconds or minutes. The longer it runs the more allocations you'll have. It's good to let the application run for a while because the initialization of the engine causes some allocations to happen, and running for too short of a time period will result in the initialization being the majority of your allocations.

  9. Once you're finished, simply close your application, or click the "Kill application" button.

  10. Once the application ends, the CLR Profiler will generate a log. A window will appear which provides access to the information in the log.

Reading the results - Allocations by object type

Allocations by method

<root> X.X MB (100.00%)

Skipping Initialization

  • Cache off the Texture2D for "redball.bmp" and use that as an argument instead of calling Load.

  • Try calling AddParticleSprite instead of AddSprite.

  • Try creating your own pool of Sprites which you add and remove from the SpriteManager.

You can find more performance-enhancing solutions in the Performance Tutorials section.

Troubleshooting the CLR Profiler

Sometimes the CLR Profiler is a little tricky to get running. If you're having problems with the CLR profiler, try the following:

  • Copy the CLR Profiler binary files (exes and dlls) to the location where your game's EXE is located and then try running the CLR Profiler

  • Right-click on each .dll and each .pdb used by the CLR Profiler, select "Properties", then click the "Unblock" button

  • Run the CLR Profiler as administrator

  • Turn Memory Allocations on, but turn profiling off, then turn profiling back on when the app is running.

Last updated