Heap Allocations Viewer plugin

When we first launched ReSharper 8 back in July last year, there was a very nice little feature hidden in internal mode. This was being used by the dev team to help keep an eye on performance. It was a little checkbox that said “Show allocations (delegates, closures, hidden allocations, boxing)”.

It added highlights to your code, as you type, indicating where memory is being allocated. It’s very eye-opening to see how frequently memory is allocated, and often in places you don’t expect. Take this call to a function with “params” arguments. Note the orange highlight, telling us that .net will allocate an array for the parameters, for each call:

Highlight hidden allocation of an array

But alas, features hidden in our internal mode are not very discoverable. So the developer behind the feature, Alexander Shvedov, made a few changes, fixed a few issues and pulled it out into an extension, which is now available to download from the extension manager, by searching for “heapview“. A stable version 0.9.1 is available, but you can always live on the edge by installing a prerelease version.

Extension Manager showing heapview extension

WARNING: Before we go any further, it must be said: BEWARE OF PREMATURE OPTIMISATION.

This plugin will tell you when an allocation is made, but it does not tell you how much memory is being allocated, or how frequently. It does not tell you if you have memory problems with your application. It simply shows where allocations are going to occur. You should still use a memory profiler such as dotMemory to measure your application and decide if your memory usage is causing you issues.

But of course, the plugin is still very useful. It’s always good to know what your code is doing, and having that visible can help you to make more informed design decisions. It’s also very helpful when you know you need to write code that should avoid excessive allocations. For example, the dev team use this to keep an eye on memory allocations made during performance critical code paths, such as as-you-type analysis. These code paths are called very frequently, every time you edit a document, and obviously need to be fast. Memory churn can have a huge impact on performance especially if it causes garbage collection, so even a small amount of allocations in these circumstances can have a knock on effect on performance.

And of course, it’s simply a very interesting view into what your code is doing!

So what does it highlight?

Obviously, it handles explicit allocation, with the new keyword:

Highlight explicit allocation

And it also supports the standard ReSharper functionality of changing the severity of the highlight (so you can disable it if you’re not interested in that particular highlight) and allows you to find all similar highlights in the project or solution.

Configure severity and find all in scope

Other heap allocations:

Example heap allocation highlights

The plugin will highlight allocations made due to boxing:

Highlight boxing allocations

Delegate creation, even listing local scope variables that are captured in closures:

Highlight delegate creation

It will even show you the points where the classes used to capture closure variables are created:

Highlight closure allocation

You can use this plugin in combination with a full profiler, such as dotMemory. Here’s an example where the plugin reports a possible enumerator allocation:

Possible enumerator allocation

When profiling this code using dotMemory and capturing memory allocations, we can see that the plugin is right: generic array enumerators are being allocated (of type SZArrayHelper+SZGenericArrayEnumerator<String>) and collected all the time, potentially triggering garbage collections! The backtrace also shows us that these allocations originate from Method1:

Allocations in dotMemory

Our code would be more performant and less heavy on memory traffic if we just enumerated the args array instead of casting it to an IEnumerable<string>.

As we can see, once you’ve found your allocation hotspots with the profiler, the plugin will make it obvious where in the method the memory is being allocated, whether it be explicitly, or through hidden allocations such as boxing or capturing closure information.

And of course, it’s Open Source. If you’re interested to see how it’s written, or want to report issues, or perhaps even contribute, please check it out.

Comments below can no longer be edited.

11 Responses to Heap Allocations Viewer plugin

  1. Avatar

    Peter says:

    June 6, 2014

    You are great! This is awesome!

  2. Avatar

    Cengiz Ilerler says:

    June 9, 2014

    Thank you! Really great one!

    In following line, it reports on bold part Boxing allocation: conversion from value type ‘DateTime’ to reference type ‘object’

    string.Format(“{0:yyyyMMdd},{1},{2}”, Date, Description, Link);

    Also this one has no warning at all.

    string.Format(“{0},{1},{2}”, Date.ToString(“yyyyMMdd”), Description, Link);

    I was wondering if we should always use it like that? I mean it is kind of a feature that use a lot but didn’t realize, that is something I shouldn’t do until now.

    Thank you again!

    • Avatar

      Matt Ellis says:

      June 9, 2014

      The first example boxes the Date value type, because it needs to be converted to an object so it can be passed to the string.Format method (which will then call ToString). The second calls ToString explicitly, and since string is an object, no boxing needs to happen.

      It’s probably a good idea to follow this pattern for value types, since you’re saving a boxing allocation each time you do this, but you should only really change your code when you know it’s causing you an issue.

      In other words, if you measure this and find that the code is only called once, then optimising for a single boxing allocation won’t help much. But if this code is in a critical path, called frequently, then the allocations might add up to make it worth changing the code.

      So, the answer is the traditional “it depends”. Be wary of anyone who says to *always* do this. Measure and see if it makes sense to change your code. But the plugin will give you a good idea that allocations are happening, and help you spot areas that are probably worth profiling.

      • Avatar

        Cengiz Ilerler says:

        June 9, 2014

        Thank you for the detailed explanation.

  3. Avatar

    Richard Moss says:

    June 9, 2014

    Looks nice, but the very first thing I saw was it was highlighting exceptions, ie “throw new NotImplementedException();”. Don’t know how possible it is, but would be nice if it could detect calls to throwing exceptions and not highlight them – it’s not like you are going to optimize them away, premature or not 🙂 Otherwise this is looking like something that could be helpful; thanks!

    Richard Moss

  4. Avatar

    repka says:

    June 20, 2014

    For code:

    void Do(T[] items)
        foreach (var i in items.Where(i => i != null))

    it marks lambda sign with ‘Slow delegate creation: anonymous function in generic method is generic itself’ which is marked by default as error. Can you go into detail what is wrong with it? Thanks

    • Avatar

      repka says:

      June 20, 2014

      Do() is a generic method, I can’t figure out how to get type parameter to render properly in these comments.

      • Avatar

        controlflow says:

        June 23, 2014

        Hi! This plugin also has one more internal feature: code inspection to show ‘slow’ (>10x slower) delegate instance creations for CLR x86 JIT. You can run this test (it creates delegates from various kinds of methods – virtual/interface/generic/etc) to see the difference in delegate creation performance.

        Just as with allocations inspection – you shouldn’t care about this much until some performance snapshot in some hot path of your application shows long invocations of CLR internals. And just like with allocations – this inspections may (and will) produce false positives with new RuyJIT, for example.

  5. Avatar

    Ondrej says:

    August 1, 2014

    The funny thing is, that when I pass, for instance, an int argument to the string.Format() method that the extension warns me about boxing and when I append .ToString() then R# claims that the call is redundant. But this call solves the problem, doesn’t it? At least the extension does not complain anymore. It’s not visible in the .NET source code how is this conversion done. Is boxing internally still required?

    • Avatar

      Darcy says:

      October 24, 2016

      It is a trade off. Messier code (in this case) makes for less un/boxing, but is less maintainable. In general you should go with more maintainable (unless it will obviously have terrible performance). However if found this code was on a Hotpath, you should go with less maintainable but faster. As with any perf coding you should be profiling to see how effective the change would be.

Discover more