Nine months ago I blogged about our MiniProfiler open source project. I used some hyperbole in the announcement blog. I goaded others to port MiniProfiler to their favourite web stack and accused us of living in the “stone age” of web profiling.

MiniProfiler attracted many lovers and some haters who either hated my marketing hyperbole speak or said that “real” profilers do not make you litter your code with superfluous profiling code. I responded with some helpers that allow you to automatically instrument your web apps. MiniProfiler does not prescribe profiling blocks, you can get very rich instrumentation with minimal changes to your code.

Exaggeration aside, awesome is infectious. PHP now has a port of MiniProfiler, Python has a port of MiniProfiler.

What problem is Mini Profiler Solving?

The main goal has always been, increase developer awareness around performance bottlenecks. Instead of simply “feeling” that a page “may” be slow. MiniProfiler tells you why it is slow. It is in your face telling you to remove the suck from your code.

With this in mind we made a few great evolutionary improvements to Mini Profiler.

Front end performance analysis

In 1968 Robert Miller wrote:

[Regarding] response to request for next page … Delays of longer than 1 second will seem intrusive on the continuity of thought

This was still true in the canonical Jacob Nielsen article 30 year later, it is still true today. We strive to have 100ms response time… everywhere.

However, the pesky speed of light thing keeps on getting in the way as does the stateless nature of the web.

As developers we often think that we only have control over performance problems in the server room, or equipment we own. The harsh reality is that the largest amount of pain is introduced in the front end, often the largest bang for buck is improving the front end.

MiniProfiler now allows you to measure your front end performance. This is accomplished by using Navigation Timings API. It is supported on Chrome, Firefox and IE9 (notably Opera and Safari are missing support for these APIs)

Additionally, you can add your own client side probes to measure the impact of your JavaScript includes and CSS. This allows you to easily share this information with your team, without needing fancy screen shots.

To add client side probes in an ASP.NET MVC app you would amend your master layout like this:

@using StackExchange.Profiling; 
....
<head>
@this.InitClientTimings();
@this.TimeScript("jQuery", 
    @<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>)

The following will insert a simple JavaScript probe framework into your page and wrap your includes with it.

<script type="text/javascript">mPt=function(){var t=[];return{t:t,probe:function(n){t.push({d:new Date(),n:n})}}}()</script>
<script type="text/javascript">mPt.probe('jQuery')</script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">mPt.probe('jQuery')</script>

Take this trace, for example, here is an initial request to the meta home page:

initial request to meta home page

Here is a repeat request:

trace with client timing API

We may have a false sense of security thinking that our page only took 13 or so ms server side. My actual perceived user performance was waiting a long time before I saw anything. For the first case I waited 1.5 seconds before the CSS was evaluated. For a repeat view I waited 423ms till the CSS finished evaluating and the page even started rendering.

Tools like firebug, chrome dev tools or IE dev tools do not clearly report these times:

chrome

Looking at the screenshot from chrome we may think, incorrectly, that putting this script in the header had no impact. Note that speed tracer does show these timings and more, however, is not ubiquitous.

So, what can you do with this kind of information?

  • You can invest time in pushing scripts to the footer and perhaps loading them async.
  • You can start building a case for getting a CDN or a better CDN.
  • You can look at minimizing scripts, CSS includes and trimming them down.
  • You can easily share this information with your team, without needing to take awkward screen shots - you simply share a link.
  • You can start thinking about crazy things, like replicating your database globally and serving pages from the closest location.
  • And so on.

UI less profiling

In the past when MiniProfiler was on, the UI was always there. This is perfect for developers but makes it impossible to gather information about requests that are not coming from developers.

You can now enable profiling on any page in a UI-less mode. To do so, simply render your MiniProfiler include and start a session.

To start a session use the same API you did in the past:

In your Global.asax.cs file:

// Tell MiniProfiler if the current request can see the UI. 
void Application_Start(object sender, EventArgs e) 
{
   MiniProfiler.Settings.Results_Authorize = httpRequest => IsUserAllowedToSeeMiniProfilerUI(httpRequest);
}

protected void Application_BeginRequest() 
{
   if (wouldLikeToGatherProfilingInfoAboutThisRequest)
   {
      profiler = MiniProfiler.Start();
   }
}

protected void Application_EndRequest()
{
   MiniProfiler.Stop();
}

The last thing in your master layout:

@if (wouldLikeToGatherProfilingInfoAboutThisRequest) {
   @MiniProfiler.RenderIncludes()
}

Experimental list everything UI

We added a simple UI to list the recent 100 sessions. This allows you to view session you did not participate in and have no links to. The UI, we are accepting patches to spruce it up.

You can view it by going to http://your-sites/mini-profiler-resources/results-index

list UI

This UI is not enabled by default. You will need to “allow” users to see it:

MiniProfiler.Settings.Results_List_Authorize = (request) =>
{
    // you may implement this if you need to restrict visibility of profiling lists on a per request basis 
    return true; // all requests are kosher
};

Script re-organisation

MiniProfiler always used jquery.tmpl for client side rendering. This plugin was “bolted on” to the current jQuery object. The trouble was that sometimes people decided to bolt on their own templating plugins and we stepped on each others feet.

The new version of MiniProfiler ships a stand alone version of jQuery and jquery.tmpl that are used in a .noCoflict() mode. This mean you can have whatever version of jQuery you wish and it will not conflict with MiniProfiler.

Defer everything

In the past we expected MiniProfiler to be included in the header of the page, the new design encourages you to place MiniProfiler.RenderIncludes() in your footer (if you don’t it will still attempt to load async). This means that we can accurately measure client side timings without interfering with your page render.

No longer MVCMiniProfiler

From launch we always allowed profiling of Web Forms and ASP.NET MVC apps. Mark Young submitted patches for improving EF support and added WCF support. Yet all projects where stuck importing an awkward namespace called MVCMiniProfiler. For the 2.0 release we shuffled around all the assembly names to use the StackExchange.Profiling namespace. This sends a better message to the community about the purpose of the MiniProfiler project.

When upgrading you need to replace:

using MVCMiniProfiler

With

using StackExchange.Profiling

Other changes

  • Results_Authorize used to take in a MiniProfiler object, now it does not.
  • MiniProfiler.EF now has a special method for initializing profiling for EF 4.2 Initialize_EF42
  • StackExchange.Profiling.Storage.IStorage has a new List that is used to query data in the list mode

Where Do I get it?

We uploaded MiniProfiler , MiniProfiler.EF and MiniProfiler.MVC to nuget. While we are finalizing the 2.0 release you will need to install it from the Package Manager Console:

edit MiniProfiler 2.0 has now been released

PM> Install-Package MiniProfiler

A call to action

MiniProfiler has no website, MiniProfiler could have better documentation, MiniProfiler has not been ported to Ruby-on-Rails, Django, Lift or whatever other awesome web framework you may be using.

Contact me if:

  1. You would like to help built a site for MiniProfiler or get it a domain.
  2. You would like pointers porting it to your web framework
  3. You would like to take ownership of the MiniProfiler.WCF package (which is missing from nuget)

If there are any bugs you discover please report them here: Google Code Archive - Long-term storage for Google Code Project Hosting.

If you would like to help improve our documentation edit our little tag wiki and make it awesome.

Patches are always welcome, personally I prefer getting them on github.

Big thanks to Jarrod who designed much of the MiniProfiler internals and the community at large for the patches and support that got us to a 2.0 release.

Comments

Bill about 12 years ago
Bill

Sam, Can someone tell me the difference between the various Nuget packages? i.e. MiniProfiler, MiniProfiler.EF, and MiniProfiler.MVC.

Sam Saffron about 12 years ago
Sam Saffron

MiniProfiler is all you need, MiniProfiler.MVC contains sample code for integration. MiniProfiler.EF is required if you are profiling entity framework … there are too many hacks to keep it in core.

Jesse about 12 years ago
Jesse

Will it be possible to log results back to a database? Also, how much overhead (nothing specific, just a ballpark) does including the profiler on a request add?

Sam Saffron about 12 years ago
Sam Saffron

sure, we have an implementation of IStorage that talks to Sql Server. You would need to test for overhead, if you disable stack traces and have a sane amount of profiling it should be low impact.

S_Ren_Truds_Mahon about 12 years ago
S_Ren_Truds_Mahon

Very nice.

It would be awesome if it was possible to export the client side logging to HAR, to further analysis.

Maybe just integrate: HARViewer?

Christian_Walde about 12 years ago
Christian_Walde

Sam, a while ago i opened a bug on your google code site asking for a demo site so i could work on porting it to Perl and you pointed out data.stackexchange. Thanks a lot for that! Since then i've been working on it on and off, and today i've managed to get it thrown together in a fashion that actually works with the main features. You can see a running demo of this on http://mp.eatsmou.se and you can also find a link to my github repo there.

Something i'm sure you'll appreciate is that due to my choice of implementing this as a Plack middleware, the MiniProfiler will work for all remotely modern Perl frameworks, since all of them make it possible and easy to use Plack as a server communication layer.

Something i'd like to ask of you is to take a look at the repo and the demo and let me know if you have any thoughts on them, things you think i misunderstood or should concentrate on, etc. If you do this and have comments, you can also send a message to the email address used to post this.

Lastly, do you hang out in any IRC channels so i could maybe get some realtime feedback instead of guessing how C# works? :)

Sam Saffron about 12 years ago
Sam Saffron

love this, you are going to need to add caching for the resources you are serving, ping me via my email at sam.saffrongmail

Tim_Waddell about 12 years ago
Tim_Waddell

Hey Sam,

Installed pkg MiniProfiler.EF 2.0.0 but creates empty package folder?

Assume StackExchange.Profiling.Data.EntityFramework .dll is meant to be in there?

Sam Saffron about 12 years ago
Sam Saffron

hmm sounds like I messed up, will get it fixed

Tomi_Junnila about 12 years ago
Tomi_Junnila

As Tim Waddell pointed out, MiniProfiler.EF is empty; this seems to be due to the .nuspec file referring to “StackExchange.Profiling.EntityFramework.*”, but the assembly name in the .csproj being “MiniProfiler.EntityFramework”.

Sam Saffron about 12 years ago
Sam Saffron

This is now sorted

Felipe about 12 years ago
Felipe

Do you have any plan to make it compatible with Medium Trust?

Thx

Felipe about 12 years ago
Felipe

Sam, I did some tests and Full trust is required just to get MiniProfiler.Settings.Version.

This two lines:

            using (var sha256 = System.Security.Cryptography.SHA256.Create())
                Version = System.Convert.ToBase64String(sha256.ComputeHash(contents));

I am sending you a patch

Tom almost 12 years ago
Tom

Looks like the MVC package is called MiniProfiler.MVC3, not MiniProfiler.MVC.

Mark almost 12 years ago
Mark

Sam, first of all – thank you for Mini Profiler :)

I'd like to know what is best way to disable Mini Profiler? I use Performance Profiler in VS2010, and MP interferes. I'd like to temporarly, reduce such an interference.

Sam Saffron almost 12 years ago
Sam Saffron

well, just don’t start it if a global setting is enabled …

Srikanth over 11 years ago
Srikanth

Sam, does MiniProfiler.MVC work with ASP.NET MVC3 AsyncController as is? can you add a sample somewhere for reference. Thanks.


comments powered by Discourse