When a program is built with memory profiling enabled and uses the Boehm garbage collector, i.e. a grade with ‘.memprof.gc’ modifiers, each memory cell is “attributed” with information about its origin and type. This information can be collated to tell you what kinds of objects are being retained when the program executes.
To do this, you must instrument the program by adding calls to
at points of interest.
The first argument of the
report_memory_attribution predicates is a
string that is used to label the memory retention data corresponding to that
call in the profiling output.
You may want to call them from within ‘trace’ goals:
trace [run_time(env("SNAPSHOTS")), io(!IO)] ( benchmarking.report_memory_attribution("Phase 2", !IO) )
If a program operates in distinct phases you may want to add a call in between the phases. The ‘report_memory_attribution’ predicates do nothing in other grades, so are safe to leave in the program.
Next, build the program in a ‘.memprof.gc’ grade. After the program has finished executing, it will generate a file called ‘Prof.Snapshots’ in the current directory. Run ‘mprof -s’ to view the profile. You will see the memory cells which were on the heap at each time that ‘report_memory_attribution’ was called: the origin of the cells, and their type constructors.
Passing the option ‘-T’ will group the profile first by type constructors, then by procedure. The ‘-b’ option produces a brief profile by hiding the secondary level of information. Memory cells allocated by the Mercury runtime system itself are normally excluded from the profile; they can be viewed by passing the ‘-r’ option.
Note that Mercury values which are dead may in fact be still reachable from the various execution stacks. This is particularly noticeable on the high-level C back-end, as the C compiler does not take conservative garbage collection into account and Mercury values may linger on the C stack for longer than necessary. The low-level C grades should suffer to a lesser extent.
The attribution requires an extra word of memory per cell, which is then rounded up by the memory allocator. This is accounted for in ‘mprof’ output, but the memory usage of the program may be significantly higher than in non-memory profiling grades.