blob: 7ff37cdaf63507cbbd39fb78c32720bf599447f2 [file] [log] [blame]
<?xml version="1.0"?> <!-- -*- sgml -*- -->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
[ <!ENTITY % vg-entities SYSTEM "../../docs/xml/vg-entities.xml"> %vg-entities; ]>
<chapter id="ms-manual" xreflabel="Massif: a heap profiler">
<title>Massif: a heap profiler</title>
<emphasis>Please note that this documentation describes Massif version 3.3.0
and later. Massif was significantly overhauled for 3.3.0; versions 3.2.3
and earlier presented the profiling information an a quite different manner,
and so this documentation only pertains to the later versions.</emphasis>
<para>To use this tool, you must specify
<computeroutput>--tool=massif</computeroutput> on the Valgrind
command line.</para>
<sect1 id="ms-manual.spaceprof" xreflabel="Heap profiling">
<title>Heap profiling</title>
<para>Massif is a heap profiler. It measures how much heap memory your
program uses. This includes both the useful space, and the extra bytes
allocated for book-keeping purposes and alignment purposes. It can also
measure the size of your program's stack(s), although it does not do so by
default.</para>
<para>Heap profiling can help you reduce the amount of memory your program
uses. On modern machines with virtual memory, this provides the following
benefits:</para>
<itemizedlist>
<listitem><para>It can speed up your program -- a smaller
program will interact better with your machine's caches and
avoid paging.</para></listitem>
<listitem><para>If your program uses lots of memory, it will
reduce the chance that it exhausts your machine's swap
space.</para></listitem>
</itemizedlist>
<para>Also, there are certain space leaks that aren't detected by
traditional leak-checkers, such as Memcheck's. That's because
the memory isn't ever actually lost -- a pointer remains to it --
but it's not in use. Programs that have leaks like this can
unnecessarily increase the amount of memory they are using over
time. Massif can help identify these leaks.</para>
<para>Importantly, Massif tells you not only how much heap memory your
program is using, it also gives very detailed information that indicates
which parts of your program are responsible for allocating the heap memory.
</para>
</sect1>
<sect1 id="ms-manual.using" xreflabel="Using Massif">
<title>Using Massif</title>
<para>First off, as for the other Valgrind tools, you should compile with
debugging info (the <computeroutput>-g</computeroutput> flag). It shouldn't
matter much what optimisation level you compile your program with, as this
is unlikely to affect the heap memory usage.</para>
<para>Then, to gather heap profiling information about the program
<computeroutput>prog</computeroutput>, type:</para>
<screen><![CDATA[
% valgrind --tool=massif prog
]]></screen>
<para>The program will execute (slowly). Upon completion, no summary
statistics are printed to Valgrind's commentary; all of Massif's profiling
data is written to a file. By default, this file is called
<filename>massif.out.&lt;pid&gt;</filename>, where
<filename>&lt;pid&gt;</filename> is the process ID.</para>
<para>To see the information gathered by Massif in an easy-to-read form, use
the ms_print script. If the output file's name is
<filename>massif.out.12345</filename>, type:</para>
<screen><![CDATA[
% ms_print massif.out.12345]]></screen>
<para>ms_print will produce (a) a graph showing the memory consumption over
the program's execution, and (b) detailed information about the responsible
allocation sites at various points in the program, including the point of
peak memory allocation. The use of a separate script for presenting the
results is deliberate: it separates the data gathering from its
presentation, and means that new methods of presenting the data can be added in
the future.</para>
<sect2 id="ms-manual.anexample" xreflabel="An Example">
<title>An Example Program</title>
<para>An example will make things clear. Consider the following C program
(annotated with line numbers) which allocates a number of different blocks
on the heap.</para>
<screen><![CDATA[
1 #include <stdlib.h>
2
3 void g(void)
4 {
5 malloc(4000);
6 }
7
8 void f(void)
9 {
10 malloc(2000);
11 g();
12 }
13
14 int main(void)
15 {
16 int i;
17 int* a[10];
18
19 for (i = 0; i < 10; i++) {
20 a[i] = malloc(1000);
21 }
22
23 f();
24
25 g();
26
27 for (i = 0; i < 10; i++) {
28 free(a[i]);
29 }
30
31 return 0;
32 }
]]></screen>
</sect2>
<sect2 id="ms-manual.theoutputpreamble" xreflabel="The Output Preamble">
<title>The Output Preamble</title>
<para>After running this program under Massif, the first part of ms_print's
output contains a preamble which just states how the program, Massif and
ms_print were each invoked:</para>
<screen><![CDATA[
--------------------------------------------------------------------------------
Command: example
Massif arguments: (none)
ms_print arguments: massif.out.12797
--------------------------------------------------------------------------------
]]></screen>
</sect2>
<sect2 id="ms-manual.theoutputgraph" xreflabel="The Output Graph">
<title>The Output Graph</title>
<para>The next part is the graph that shows how memory consumption occurred
as the program executed:</para>
<screen><![CDATA[
KB
19.63^ #
| #
| #
| #
| #
| #
| #
| #
| #
| #
| #
| #
| #
| #
| :#
| :#
| :#
| :#
| :#
| :#
0 +----------------------------------------------------------------------->ki
0 121.8
Number of snapshots: 25
Detailed snapshots: [9, 14 (peak), 24]
]]></screen>
<para>Why is most of the graph empty, with only a couple of bars at the very
end? By default, Massif uses "instructions executed" as the unit of time.
For very short-run programs such as the example, most of the executed
instructions involve the loading and dynamic linking of the program. The
execution of <computeroutput>main</computeroutput> (and thus the heap
allocations) only occur at the very end. For a short-running program like
this, we can use the <computeroutput>--time-unit=B</computeroutput> option
to specify that we want the time unit to instead be the number of bytes
allocated/deallocated on the heap and stack(s).</para>
<para>If we re-run the program under Massif with this option, and then
re-run ms_print, we get this more useful graph:</para>
<screen><![CDATA[
KB
19.63^ #
| # .
| # : .
| # : : .
| : # : : : .
| : # : : : : .
| : # : : : : : .
| : # : : : : : : .
| : : # : : : : : : : .
| : : # : : : : : : : : .
| : : : # : : : : : : : : : ,
| @ : : : # : : : : : : : : : @
| : @ : : : # : : : : : : : : : @
| : : @ : : : # : : : : : : : : : @
| : : : @ : : : # : : : : : : : : : @
| : : : : @ : : : # : : : : : : : : : @
| : : : : : @ : : : # : : : : : : : : : @
| : : : : : : @ : : : # : : : : : : : : : @
| : : : : : : : @ : : : # : : : : : : : : : @
| : : : : : : : : @ : : : # : : : : : : : : : @
0 +----------------------------------------------------------------------->KB
0 29.48
Number of snapshots: 25
Detailed snapshots: [9, 14 (peak), 24]
]]></screen>
<para>Each vertical bar represents a snapshot, i.e. a measurement of the
memory usage at a certain point in time. The text at the bottom show that
25 snapshots were taken for this program, which is one per heap
allocation/deallocation, plus a couple of extras. Massif starts by taking
snapshots for every heap allocation/deallocation, but as a program runs for
longer, it takes snapshots less frequently. It also discards older
snapshots as the program goes on; when it reaches the maximum number of
snapshots (100 by default, although changeable with the
<computeroutput>--max-snapshots</computeroutput> option) half of them are
deleted. This means that a reasonable number of snapshots are always
maintained.</para>
<para>Most snapshots are <emphasis>normal</emphasis>, and only basic
information is recorded for them. Normal snapshots are represented in the
graph by bars consisting of ':' and '.' characters.</para>
<para>Some snapshots are <emphasis>detailed</emphasis>. Information about
where allocations happened are recorded for these snapshots, as we will see
shortly. Detailed snapshots are represented in the graph by bars consisting
of '@' and ',' characters. The text at the bottom show that 3 detailed
snapshots were taken for this program (snapshots 9, 14 and 24). By default,
every 10th snapshot is detailed, although this can be changed via the
<computeroutput>--detailed-freq</computeroutput> option.</para>
<para>Finally, there is at most one <emphasis>peak</emphasis> snapshot. The
peak snapshot is a detailed snapshot, and records the point where memory
consumption was greatest. The peak snapshot is represented in the graph by
a bar consisting of '#' and ',' characters. The text at the bottom shows
that snapshot 14 was the peak. Note that for tiny programs that never
deallocate heap memory, Massif will not record a peak snapshot.</para>
<para>Some more details about the peak: the peak is determined by looking
at every allocation, i.e. it is <emphasis>not</emphasis> just the peak among
the regular snapshots. However, recording the true peak is expensive, and
so by default Massif records a peak whose size is within 1% of the size of
the true peak. See the description of the
<computeroutput>--peak-inaccuracy</computeroutput> option below for more
details.</para>
<para>The following graph is from an execution of Konqueror, the KDE web
browser. It shows what graphs for larger programs look like.</para>
<screen><![CDATA[
MB
3.952^ #.
| ,@#:
| , .. :@@#:
| @ :: :@@#:.
| ,@ :: :@@#::
| , .@@@ :: :@@#:.
| .@ :@@@ :: :@@#::
| : :@ :@@@ :: :@@#::
| ,: :@ :@@@ :: :@@#::
| ,:@: :@ :@@@ :: :@@#::.
| @@:@: :@ :@@@ :: :@@#:::
| ,,: .:: . , .::@@:@: :@ :@@@ :: :@@#:::
| .:@@: .: ::: ::: @ :::@@:@: :@ :@@@ :: :@@#:::
| ,: ::@@: ::: ::::::: @ :::@@:@: :@ :@@@ :: :@@#:::
| @: ::@@: ::: ::::::: @ :::@@:@: :@ :@@@ :: :@@#::.
| @: ::@@: ::: ::::::: @ :::@@:@: :@ :@@@ :: :@@#:::
| , @: ::@@:: ::: ::::::: @ :::@@:@: :@ :@@@ :: :@@#:::
| ::@ @: ::@@:: ::: ::::::: @ :::@@:@: :@ :@@@ :: :@@#:::
| , :::::@ @: ::@@:: ::: ::::::: @ :::@@:@: :@ :@@@ :: :@@#:::
| ..@ :::::@ @: ::@@:: ::: ::::::: @ :::@@:@: :@ :@@@ :: :@@#:::
0 +----------------------------------------------------------------------->Mi
0 626.4
Number of snapshots: 63
Detailed snapshots: [3, 4, 10, 11, 15, 16, 29, 33, 34, 36, 39, 41,
42, 43, 44, 49, 50, 51, 53, 55, 56, 57 (peak)]
]]></screen>
<para>Note that the larger size units are KB, MB, GB, etc. As is typical
for memory measurements, these are based on a multiplier of 1024, rather
than the standard SI multiplier of 1000. Strictly speaking, they should be
written KiB, MiB, GiB, etc.</para>
</sect2>
<sect2 id="ms-manual.thesnapshotdetails" xreflabel="The Snapshot Details">
<title>The Snapshot Details</title>
<para>Returning to our example, the graph is followed by the detailed
information for each snapshot. The first nine snapshots are normal, so only
a small amount of information is recorded for each one:</para>
<screen><![CDATA[
--------------------------------------------------------------------------------
n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B)
--------------------------------------------------------------------------------
0 0 0 0 0 0
1 1,008 1,008 1,000 8 0
2 2,016 2,016 2,000 16 0
3 3,024 3,024 3,000 24 0
4 4,032 4,032 4,000 32 0
5 5,040 5,040 5,000 40 0
6 6,048 6,048 6,000 48 0
7 7,056 7,056 7,000 56 0
8 8,064 8,064 8,000 64 0
]]></screen>
<para>Each normal snapshot records several things.</para>
<itemizedlist>
<listitem><para>Its number.</para></listitem>
<listitem><para>The time it was taken. In this case, the time unit is
bytes, due to the use of
<computeroutput>--time-unit=B</computeroutput>.</para></listitem>
<listitem><para>The total memory consumption at that point.</para></listitem>
<listitem><para>The number of useful heap bytes allocated at that point.
This reflects the number of bytes asked for by the
program.</para></listitem>
<listitem><para>The number of extra heap bytes allocated at that point.
This reflects the number of bytes allocated in excess of what the program
asked for. There are two sources of extra heap bytes.</para>
<para>First, every heap block has administrative bytes associated with it.
The exact number of administrative bytes depends on the details of the
allocator. By default Massif assumes 8 bytes per block, as can be seen
from the example, but this number can be changed via the
<computeroutput>--heap-admin</computeroutput> option.</para>
<para>Second, allocators often round up the number of bytes asked for to a
larger number. By default, if N bytes are asked for, Massif rounds N up
to the nearest multiple of 8 that is equal to or greater than N. This is
typical behaviour for allocators, and is required to ensure that elements
within the block are suitably aligned. The rounding size can be changed
with the <computeroutput>--alignment</computeroutput> option, although it
cannot be less than 8, and must be a power of two.</para></listitem>
<listitem><para>The size of the stack(s). By default, stack profiling is
off as it slows Massif down greatly. Therefore, the stack column is zero
in the example.</para></listitem>
</itemizedlist>
<para>The next snapshot is detailed. As well as the basic counts, it gives
an allocation tree which indicates exactly which pieces of code were
responsible for allocating heap memory:</para>
<screen><![CDATA[
9 9,072 9,072 9,000 72 0
99.21% (9,000B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc.
->99.21% (9,000B) 0x804841A: main (example.c:20)
]]></screen>
<para>The allocation tree can be read from the top down. The first line
indicates all heap allocation functions such as <function>malloc</function>
and C++ <function>new</function>. All heap allocations go through these
functions, and so all 9,000 useful bytes (which is 99.21% of all allocated
bytes) go through them. But how were <function>malloc</function> and new
called? At this point, every allocation so far has been due to line 21
inside <function>main</function>, hence the second line in the tree. The
<computeroutput>-></computeroutput> indicates that main (line 20) called
<function>malloc</function>.</para>
<para>Let's see what the subsequent output shows happened next:</para>
<screen><![CDATA[
--------------------------------------------------------------------------------
n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B)
--------------------------------------------------------------------------------
10 10,080 10,080 10,000 80 0
11 12,088 12,088 12,000 88 0
12 16,096 16,096 16,000 96 0
13 20,104 20,104 20,000 104 0
14 20,104 20,104 20,000 104 0
99.48% (20,000B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc.
->49.74% (10,000B) 0x804841A: main (example.c:20)
|
->39.79% (8,000B) 0x80483C2: g (example.c:5)
| ->19.90% (4,000B) 0x80483E2: f (example.c:11)
| | ->19.90% (4,000B) 0x8048431: main (example.c:23)
| |
| ->19.90% (4,000B) 0x8048436: main (example.c:25)
|
->09.95% (2,000B) 0x80483DA: f (example.c:10)
->09.95% (2,000B) 0x8048431: main (example.c:23)
]]></screen>
<para>The first four snapshots are similar to the previous ones. But then
the global allocation peak is reached, and a detailed snapshot is taken.
Its allocation tree shows that 20,000B of useful heap memory has been
allocated, and the lines and arrows indicate that this is from three
different code locations: line 20, which is responsible for 10,000B
(49.74%); line 5, which is responsible for 8,000B (39.79%); and line 10,
which is responsible for 2,000B (9.95%).</para>
<para>We can then drill down further in the allocation tree. For example,
of the 8,000B asked for by line 5, half of it was due to a call from line
11, and half was due to a call from line 25.</para>
<para>In short, Massif collates the stack trace of every single allocation
point in the program into a single tree, which gives a complete picture of
how and why all heap memory was allocated.</para>
<para>Note that the tree entries correspond not to functions, but to
individual code locations. For example, if function <function>A</function>
calls <function>malloc</function>, and function <function>B</function> calls
<function>A</function> twice, once on line 10 and once on line 11, then
the two calls will result in two distinct stack traces in the tree. In
contrast, if <function>B</function> calls <function>A</function> repeatedly
from line 15 (e.g. due to a loop), then each of those calls will be
represented by the same stack trace in the tree.</para>
<para>Note also that tree entry with children in the example satisfies an
invariant: the entry's size is equal to the sum of its children's sizes.
For example, the first entry has size 20,000B, and its children have sizes
10,000B, 8,000B, and 2,000B. In general, this invariant almost always
holds. However, in rare circumstances stack traces can be malformed, in
which case a stack trace can be a sub-trace of another stack trace. This
means that some entries in the tree may not satisfy the invariant -- the
entry's size will be greater than the sum of its children's sizes. Massif
can sometimes detect when this happens; if it does, it issues a
warning:</para>
<screen><![CDATA[
Warning: Malformed stack trace detected. In Massif's output,
the size of an entry's child entries may not sum up
to the entry's size as they normally do.
]]></screen>
<para>However, Massif does not detect and warn about every such occurrence.
Fortunately, malformed stack traces are rare in practice.</para>
<para>Returning now to ms_print's output, the final part is similar:</para>
<screen><![CDATA[
--------------------------------------------------------------------------------
n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B)
--------------------------------------------------------------------------------
15 21,112 19,096 19,000 96 0
16 22,120 18,088 18,000 88 0
17 23,128 17,080 17,000 80 0
18 24,136 16,072 16,000 72 0
19 25,144 15,064 15,000 64 0
20 26,152 14,056 14,000 56 0
21 27,160 13,048 13,000 48 0
22 28,168 12,040 12,000 40 0
23 29,176 11,032 11,000 32 0
24 30,184 10,024 10,000 24 0
99.76% (10,000B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc.
->79.81% (8,000B) 0x80483C2: g (example.c:5)
| ->39.90% (4,000B) 0x80483E2: f (example.c:11)
| | ->39.90% (4,000B) 0x8048431: main (example.c:23)
| |
| ->39.90% (4,000B) 0x8048436: main (example.c:25)
|
->19.95% (2,000B) 0x80483DA: f (example.c:10)
| ->19.95% (2,000B) 0x8048431: main (example.c:23)
|
->00.00% (0B) in 1+ places, all below ms_print's threshold (01.00%)
]]></screen>
<para>The final detailed snapshot shows how the heap looked at termination.
The 00.00% entry represents the code locations for which memory was
allocated and then freed (line 20 in this case, the memory for which was
freed on line 28). However, no code location details are given for this
entry; by default, Massif only records the details for code locations
responsible for more than 1% of useful memory bytes, and ms_print likewise
only prints the details for code locations responsible for more than 1%.
The entries that do not meet this threshold are aggregated. This avoids
filling up the output with large numbers of unimportant entries. The
thresholds threshold can be changed with the
<computeroutput>--threshold</computeroutput> option that both Massif and
ms_print support.</para>
</sect2>
</sect1>
<sect1 id="ms-manual.options" xreflabel="Massif Options">
<title>Massif Options</title>
<para>Massif-specific options are:</para>
<!-- start of xi:include in the manpage -->
<variablelist id="ms.opts.list">
<varlistentry id="opt.heap" xreflabel="--heap">
<term>
<option><![CDATA[--heap=<yes|no> [default: yes] ]]></option>
</term>
<listitem>
<para>Specifies whether heap profiling should be done.</para>
</listitem>
</varlistentry>
<varlistentry id="opt.heap-admin" xreflabel="--heap-admin">
<term>
<option><![CDATA[--heap-admin=<number> [default: 8] ]]></option>
</term>
<listitem>
<para>If heap profiling is enabled, gives the number of administrative
bytes per block to use. This should be an estimate of the average,
since it may vary. For example, the allocator used by
<computeroutput>glibc</computeroutput> requires somewhere between 4 to
15 bytes per block, depending on various factors. It also requires
admin space for freed blocks, although Massif does not account
for this.</para>
</listitem>
</varlistentry>
<varlistentry id="opt.stacks" xreflabel="--stacks">
<term>
<option><![CDATA[--stacks=<yes|no> [default: yes] ]]></option>
</term>
<listitem>
<para>Specifies whether stack profiling should be done. This option
slows Massif down greatly, and so is off by default. Note that Massif
assumes that the main stack has size zero at start-up. This is not
true, but measuring the actual stack size is not easy, and it reflects
the size of the part of the main stack that a user program actually
has control over.</para>
</listitem>
</varlistentry>
<varlistentry id="opt.depth" xreflabel="--depth">
<term>
<option><![CDATA[--depth=<number> [default: 30] ]]></option>
</term>
<listitem>
<para>Maximum depth of the allocation trees recorded for detailed
snapshots. Increasing it will make Massif run somewhat more slowly,
use more memory, and produce bigger output files.</para>
</listitem>
</varlistentry>
<varlistentry id="opt.alloc-fn" xreflabel="--alloc-fn">
<term>
<option><![CDATA[--alloc-fn=<name> ]]></option>
</term>
<listitem>
<para>Functions specified with this option will be treated as though
they were a heap allocation function such as
<function>malloc</function>. This is useful for functions that are
wrappers to <function>malloc</function> or <function>new</function>,
which can fill up the allocation trees with uninteresting information.
This option can be specified multiple times on the command line, to
name multiple functions.</para>
<para>Note that overloaded C++ names must be written in full. Single
quotes may be necessary to prevent the shell from breaking them up.
For example:
<screen><![CDATA[
--alloc-fn='operator new(unsigned, std::nothrow_t const&amp;)'
]]></screen>
</para>
<para>
The full list of functions and operators that are by default
considered allocation functions is as follows.</para>
<screen><![CDATA[
malloc
calloc
realloc
memalign
__builtin_new
__builtin_vec_new
operator new(unsigned)
operator new(unsigned long)
operator new[](unsigned)
operator new[](unsigned long)
operator new(unsigned, std::nothrow_t const&)
operator new[](unsigned, std::nothrow_t const&)
operator new(unsigned long, std::nothrow_t const&)
operator new[](unsigned long, std::nothrow_t const&)
]]></screen>
</listitem>
</varlistentry>
<varlistentry id="opt.threshold" xreflabel="--threshold">
<term>
<option><![CDATA[--threshold=<m.n> [default: 1.0] ]]></option>
</term>
<listitem>
<para>The significance threshold for heap allocations, as a
percentage. Allocation tree entries that account for less than this
will be aggregated. Note that this should be specified in tandem with
ms_print's option of the same name.</para>
</listitem>
</varlistentry>
<varlistentry id="opt.peak-inaccuracy" xreflabel="--peak-inaccuracy">
<term>
<option><![CDATA[--peak-inaccuracy=<m.n> [default: 1.0] ]]></option>
</term>
<listitem>
<para>Massif does not necessarily record the actual global memory
allocation peak; by default it records a peak only when the global
memory allocation size exceeds the previous peak by at least 1.0%.
This is because there can be many local allocation peaks along the way,
and doing a detailed snapshot for every one would be expensive and
wasteful, as all but one of them will be later discarded. This
inaccuracy can be changed (even to 0.0%) via this option, but Massif
will run drastically slower as the number approaches zero.</para>
</listitem>
</varlistentry>
<varlistentry id="opt.time-unit" xreflabel="--time-unit">
<term>
<option><![CDATA[--time-unit=i|ms|B [default: i] ]]></option>
</term>
<listitem>
<para>The time unit used for the profiling. There are three
possibilities: instructions executed (i), which is good for most
cases; real (wallclock) time (ms, i.e. milliseconds), which is
sometimes useful; and bytes allocated/deallocated on the heap and/or
stack (B), which is useful for very short-run programs, and for
testing purposes, because it is the most reproducible across different
machines.</para> </listitem>
</varlistentry>
<varlistentry id="opt.detailed-freq" xreflabel="--detailed-freq">
<term>
<option><![CDATA[--detailed-freq=<n> [default: 10] ]]></option>
</term>
<listitem>
<para>Frequency of detailed snapshots. With
<computeroutput>--detailed-freq=1</computeroutput>, every snapshot is
detailed.</para>
</listitem>
</varlistentry>
<varlistentry id="opt.max-snapshots" xreflabel="--max-snapshots">
<term>
<option><![CDATA[--max-snapshots=<n> [default: 100] ]]></option>
</term>
<listitem>
<para>The maximum number of snapshots recorded. If set to N, for all
programs except very short-running ones, the final number of snapshots
will be between N/2 and N.</para>
</listitem>
</varlistentry>
<varlistentry id="opt.massif-out-file" xreflabel="--massif-out-file">
<term>
<option><![CDATA[--massif-out-file=<file> [default: massif.out.%p] ]]></option>
</term>
<listitem>
<para>Write the profile data to <computeroutput>file</computeroutput>
rather than to the default output file,
<computeroutput>massif.out.&lt;pid&gt;</computeroutput>. The
<option>%p</option> and <option>%q</option> format specifiers can be
used to embed the process ID and/or the contents of an environment
variable in the name, as is the case for the core option
<option>--log-file</option>. See <xref
linkend="manual-core.basicopts"/> for details.
</para>
</listitem>
</varlistentry>
<varlistentry id="opt.alignment" xreflabel="--alignment">
<term>
<option><![CDATA[--alignment=<n> [default: 1.0] ]]></option>
</term>
<listitem>
<para>The minimum alignment (and thus size) of heap blocks.</para>
</listitem>
</varlistentry>
</variablelist>
<!-- end of xi:include in the manpage -->
</sect1>
<sect1 id="ms-manual.ms_print-options" xreflabel="ms_print Options">
<title>ms_print Options</title>
<para>ms_print's options are:</para>
<itemizedlist>
<listitem>
<para><computeroutput>-h, --help</computeroutput></para>
<para><computeroutput>-v, --version</computeroutput></para>
<para>Help and version, as usual.</para>
</listitem>
<listitem>
<para><option><![CDATA[--threshold=<m.n>]]></option> [default: 1.0]</para>
<para>Same as Massif's <computeroutput>--threshold</computeroutput>, but
applied after profiling rather than during.</para>
</listitem>
<listitem>
<para><option><![CDATA[--x=<m.n>]]></option> [default: 72]</para>
<para>Width of the graph, in columns.</para>
</listitem>
<listitem>
<para><option><![CDATA[--y=<n>]]></option> [default: 20]</para>
<para>Height of the graph, in rows.</para>
</listitem>
</itemizedlist>
</sect1>
<sect1 id="ms-manual.fileformat" xreflabel="fileformat">
<title>Massif's output file format</title>
<para>Massif's file format is plain text (i.e. not binary) and deliberately
easy to read for both humans and machines. Nonetheless, the exact format
is not described here. This is because the format is currently very
Massif-specific. We plan to make the format more general, and thus suitable
for possible use with other tools. Once this has been done, the format will
be documented here.</para>
</sect1>
</chapter>