John Ratcliff's Code Suppository

A place where I insert my code into the anus of the Internet.

 

Saturday, March 27, 2010

Memory Tracking Utility


Today's code snippet is a very useful tool.  The default version is provided as a 32 bit windows DLL.  There is no reason the code couldn't be refactored to be used on other platforms, but that wasn't a requirement for my own personal use.

This tool is used to detect and identify memory leaks when an application exits or, more commonly, used to simply identify where all of your memory allocations are coming from.

What's nice about using this tool as a DLL, rather than source code, is that it doesn't directly affect any of your existing allocation code.

This code does *not* trap memory allocations.  You must already be doing that yourself.  What it does is allow you to track and report on those allocations.

Ideally your application would trap every single new/delete malloc/free performed.  This can be done in a variety of different ways, either by replacing the global memory allocator, or by inheriting a base allocator class.

I strongly recommend that every class in your code base inherit a default allocator class.  Then, in every location where you used to do a 'new' operator, replace that with a macro expansion which calls an inherited new operator which accepts class name, file name, and line number.

The value of the Memory Tracking report is only as good as the data you feed into it.  If you feed into it the class name, source code filename and line number for every allocation then the report will be able to give you some tremendous information identify when, how, and where, all of your memory allocations are occurring.

One problem with tracking all memory allocations is with templates.  When you do a lot of template metaprogramming it becomes difficult to know where the source allocations are occurring.  Sometimes it is useful to add additional parameters to your templates so you can better identify where the allocations are coming from.

So, here is how you actually use the MemoryTracker DLL in your application.

You need three things:

MemoryTracker.h
MemoryTrackerBinding.cpp
MemoryTracker.dll

The header file 'MemoryTracker.h' defines the pure virtual interface to the memory tracking utility.  It also declares a single global variable pointer to the Memory tracking interface and a routine to initialize the DLL.

In your code, before you do any memory allocations, initialize the MemoryTracker.dll by calling 'NVSHARE::createMemoryTracker("MemoryTracker.dll').   You should pass the name of the DLL on disk, including the full path location if necessary.

The routine 'createMemoryTracker' is in 'MemoryTrackerBinding.cpp' which will perfom a load library call on the DLL and initialize it; also setting the global variable 'gMemoryTracker'.

Once the memory tracker DLL is loaded, you can now track all memory allocations performed by your project.

First, set the logging detal level.  The options in 'setLogLevel' are:

logEveryAllocation : This will produce an enormous amount of data, and is not recommended unless you really need to track every single allocation at startup.

logEveryFrame : This will produce a summary of allocations and frees each frame.  For this to work you need to call the method 'trackFrame' once per logical 'frame' in your application.  Again, this feature is not recommended unless you are specifically wanting this data.

There are three methods for tracking your memory allocations.  They are:

'trackAlloc', 'trackRealloc', and 'trackFree'.

The enum 'MemoryType' designates what was the type/purpose of each allocation.  This will identify if it was a 'new' 'delete', a 'new array' or 'delete array', or a 'global new', etc.  The difference between MT_NEW and MT_GLOBAL_NEW, is to indicate whether the new operator was trapped or not.

When you track an allocation you can specify the class name, or simply a tag for the purpose/type of allocation, and the file name and line number of the original C++ source code.  You can do this by using the compiler preprocessor directive __FILE__ and __LINE__.

It is very important to note that these string pointers must be persistent for the lifetime of your application!  You cannot, and should not, ever pass stack or temporary variables in as the parameters!

One of the most valuable options when tracking memory is 'context'.  The 'context' allows you to organize your report based on its overall meaning within your application.  A good example of this is if you are working with a piece of middleware, like say the PhysX SDK, which allows you to provide a user allocator override.   Every time this SDK does a callback to your application for memory you can pass in as the context field 'PhysX'.  Then, when you generate the memory report, you will have all of the memory used by PhyX organized separately from the memory allocated by other parts of your application.

When you application exits, and after all memory allocated should have been freed, you can call the method 'detectMemoryLeaks'.  You pass it the filename of the HTML report you want saved.  Also you pass the option 'reportAllLeaks'.  If 'reportAllLeaks' is true then every single piece of allocated memory which was never freed will be reported in detail. 

In addition to using 'detectMemoryLeaks' to generate a report on exit, you may also call it at any time in your application simply to get a general report of overall memory usage.

If you use it for this purpose it is strongly recommended that you set 'reportAllLeaks' to false, otherwise you could generate a massive data report.

The real value of this utility is the report itself.  The output is sorted by class name, source code and line number, as well as context.  It comes with totals and subtotals and is some very nicely formatted HTML tables as output.  When I get a chance I will upload a sample report for you to take a look at.

The MemoryTracker utility is an open source project hosted on Google Code.  You an find it at the following link.

If you don't care about the source code to the memory tracker tool but simply want to download the tool try these links.

MemoryTracker.h
MemoryTrackerBinding.cpp
MemoryTracker.dll

Thursday, March 25, 2010

Any SIMD optimization specialist looking for some easy consulting work?


Anyone in the game industry who has expertise at optimizing SIMD code for PC (SSE/3D Now,etc.) Xbox-360 Altivec, and PS3 SPU, looking for some easy money doing a short term gig, let me know.

I have a handful of vanilla C++ routines which need to be optimized for these platforms using a shared math library.  It's not that I can't do it myself, it's that I am already over-committed on my time for a number of other projects.  Apparently I have the ability to pay a contractor to do some of the work, so this could be easy money for somebody who really enjoys doing low-level optimization work.

Send me an email if you are interested.

Sunday, March 21, 2010

MapFile : A tool to analyze .MAP files produced by Visual Studio and report the amount of memory being used by data and code


It really annoys me that I had to write today's code snippet.  I fully expected to be able to find an existing tool that could accomplish this basic task but after literally a couple of hours of searching the Internet for something I gave up.  In the end I had to write my own tiny console application and I am making it available here so nobody else feels like they have to write it again.

Also, if anyone reading this is really good at web stuff, it would be nice to have a website that would let you upload a .MAP file and then be able to immediately view the HTML content.

The data in this version is pretty complete.  For some reason when I parse all of the address data found in the .MAP file it doesn't add up to the exact byte count that is in the sections summary.  Maybe somebody from Microsoft can explain why that is.

The data could probably be a little better organized and it could really benefit from some hyperlinks.  That said, still all of the data you need is there.

A .MAP file is an ASCII text file that can be produced by the linker phase in Visual Studio.  Under Linux the GCC compiler can also produce a .MAP file but I have no idea if the two formats are compatible.  For my needs I was only concerned about builds that were done with Visual Studio.  This works even if you are building for XBOX as well.

A .MAP file is essentially a 'memory map' of the executable.  It describes by memory address every piece of code and data in the resulting executable file.

Unfortunately it it not very human readable.  The function names in the map file are 'decorated'; meaning they have been scrambled/compressed into a machine only readable format.  A DLL that comes with Windows called 'dbghelp.dll' can 'undecorate' these strings into their human readable form.

The MapFile console application will read in a .MAP file and output an HTML file called 'output.html' that contains tables representing all of the code and data sections in the executable.

The tables are sorted either by object name or by function name.

An executable is broken up into various 'section's and the HTML output is likewise broken up the same way.

You might ask, why would you need this tool?  Well, I suppose that is a fair question.  Let's say you are targeting an Xbox-360 console machine and your executable size is 10 megabytes.  That's just huge.  So, you are going to want to know where all of that data coming from.  Is it code and, if so, from what source files and what functions?  Is it data and, if so, what kind of data is it and where is it located?

I have set up a Google Project to host this tool.  You can find it at the following link:

MapFile on Google Code

Another reason you might want to download the source code to this tool is that it demonstrates how to use two of my most powerful code snippets.  The first is the 'InPlaceParser', which is an extremely high speed text parser and the second is 'HtmlTable' which is a code snippet that will output nicely formated HTMLTables with headers, sorted columns, and totals.

Both code snippets are really useful.