From: Nicholas Nethercote Date: Mon, 26 Nov 2007 21:59:04 +0000 (+0000) Subject: - Rewrote documentation. X-Git-Tag: svn/VALGRIND_3_3_0~63 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=01e4f950f20a27144006f8eb397e49debd328548;p=thirdparty%2Fvalgrind.git - Rewrote documentation. - Added a new time unit, instructions executed, and made it the default -- it's much more reproducible and consistent than milliseconds. Requires IRSB instrumentation and so slows down some programs (malloc-light ones such as bzip2) by about 20%, others by less. - ms_print now doesn't overwrite the x-axis in the graphs. - Added a test for --detailed-freq and --max-snapshots git-svn-id: svn://svn.valgrind.org/valgrind/trunk@7229 --- diff --git a/massif/docs/ms-manual.xml b/massif/docs/ms-manual.xml index c5ae307670..c9eec4d3f3 100644 --- a/massif/docs/ms-manual.xml +++ b/massif/docs/ms-manual.xml @@ -7,46 +7,27 @@ Massif: a heap profiler -
- Docs:
- - Mention that complex functions names are best protected with single
-   quotes, eg:
-       --alloc-fn='operator new(unsigned, std::nothrow_t const&)'
-   [XXX: that doesn't work if the option is in a .valgrindrc file or in
-    $VALGRIND_OPTS.  In m_commandline.c:add_args_from_string() need to
-    respect single quotes...]
- - Explain the --threshold=0 case -- entries with zero bytes must have
-   allocated some memory and then freed it all again.
- - Explain that no peak will be taken if no deallocations are done.
- - Explain how the stack is computed -- size is assumed to be zero when
-   code starts executing, which isn't true, but reflects what you have
-   control over in a normal program.
- - file format -- not specified, because it may change in the future to 
-   become more generic
-
- +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. To use this tool, you must specify --tool=massif on the Valgrind command line. - Heap profiling -Massif is a heap profiler. It measures how much heap -memory programs use. In particular, it can give you information -about: +Massif is a heap profiler. It measures how much heap memory your +program uses. This includes both the useful space, as well as 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. - - Heap blocks; - Heap administration blocks; - Stack sizes. - - -Heap profiling is useful to help you reduce the amount of -memory your program uses. On modern machines with virtual -memory, this provides the following benefits: +Heap profiling can help you reduce the amount of memory your program +uses. On modern machines with virtual memory, this provides the following +benefits: It can speed up your program -- a smaller @@ -63,352 +44,423 @@ 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. - - - - -Why Use a Heap Profiler? - -Everybody knows how useful time profilers are for speeding -up programs. They are particularly useful because people are -notoriously bad at predicting where are the bottlenecks in their -programs. - -But the story is different for heap profilers. Some -programming languages, particularly lazy functional languages -like Haskell, have -quite sophisticated heap profilers. But there are few tools as -powerful for profiling C and C++ programs. - -Why is this? Maybe it's because C and C++ programmers must -think that they know where the memory is being allocated. After -all, you can see all the calls to -malloc() and -new and -new[], right? But, in a big -program, do you really know which heap allocations are being -executed, how many times, and how large each allocation is? Can -you give even a vague estimate of the memory footprint for your -program? Do you know this for all the libraries your program -uses? What about administration bytes required by the heap -allocator to track heap blocks -- have you thought about them? -What about the stack? If you are unsure about any of these -things, maybe you should think about heap profiling. - -Massif can tell you these things. - -Or maybe it's because it's relatively easy to add basic -heap profiling functionality into a program, to tell you how many -bytes you have allocated for certain objects, or similar. But -this information might only be simple like total counts for the -whole program's execution. What about space usage at different -points in the program's execution, for example? And -reimplementing heap profiling code for each project is a -pain. - -Massif can save you this effort. +time. Massif can help identify these leaks. - +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. + - Using Massif - -Overview +First off, as for the other Valgrind tools, you should compile with +debugging info (the -g flag). It shouldn't +matter much what optimisation level you compile your program with, as this +is unlikely to affect the heap memory usage. -First off, as for normal Valgrind use, you probably want to -compile with debugging info (the --g flag). But, as opposed to -Memcheck, you probably do want to turn -optimisation on, since you should profile your program as it will -be normally run. - -Then, run your program with valgrind ---tool=massif in front of the normal command -line invocation. When the program finishes, Massif will print -summary space statistics. It also creates a graph showing -the program's overall heap usage in a file called -massif.pid.ps, which can be read by any -PostScript viewer, such as Ghostview. - -It also puts detailed information about heap consumption in -a file massif.pid.txt (text format) or -massif.pid.html (HTML format), where -pid is the program's process id. +Then, to gather heap profiling information about the program +prog, type: + + +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 +massif.out.<pid>, where +<pid> is the process ID. + +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 +massif.out.12345, type: + - +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 ones of presenting the data can be added in +the future. + +An Example Program - -Basic Results of Profiling +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. -To gather heap profiling information about the program -prog, type: - -The program will execute (slowly). Upon completion, -summary statistics that look like this will be printed: - - -All measurements are done in -spacetime, i.e. space (in bytes) multiplied -by time (in milliseconds). Note that because Massif slows a -program down a lot, the actual spacetime figure is fairly -meaningless; it's the relative values that are -interesting. - -Which entries you see in the breakdown depends on the -command line options given. The above example measures all the -possible parts of memory: - - - Heap: number of words allocated on the heap, via - malloc(), - new and - new[]. - - - Heap admin: each heap block allocated requires some - administration data, which lets the allocator track certain - things about the block. It is easy to forget about this, and - if your program allocates lots of small blocks, it can add - up. This value is an estimate of the space required for this - administration data. - - - Stack(s): the spacetime used by the programs' stack(s). - (Threaded programs can have multiple stacks.) This includes - signal handler stacks. - - + 1 #include + 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 } +]]> - -Spacetime Graphs - -As well as printing summary information, Massif also -creates a file showing the overall spacetime behaviour of the -program, in a file -called massif.pid.ps, which can be viewed in -a PostScript viewer. - -Massif uses a program called -hp2ps to convert the raw data -into the PostScript graph. It's distributed with Massif, but -came originally from the -Glasgow Haskell -Compiler. You shouldn't need to worry about this at all. -However, if the graph creation fails for any reason, Massif will -tell you, and will leave behind a file named -massif.pid.hp, containing the raw heap -profiling data. - -Here's an example graph: - - - - - - Spacetime Graph - - - -The graph is broken into several bands. Most bands -represent a single line of your program that does some heap -allocation; each such band represents all the allocations and -deallocations done from that line. Up to twenty bands are shown; -less significant allocation sites are merged into "other" and/or -"OTHER" bands. The accompanying text/HTML file produced by -Massif has more detail about these heap allocation bands. Then -there are single bands for the stack(s) and heap admin -bytes. - - -Note: -it's the height of a band that's important. Don't let the -ups and downs caused by other bands confuse you. For example, -the read_alias_file band in the -example has the same height all the time it's in existence. - - -The triangles on the x-axis show each point at which a -memory census was taken. These aren't necessarily evenly spread; -Massif only takes a census when memory is allocated or -deallocated. The time on the x-axis is wallclock time, which is -not ideal because you can get different graphs for different -executions of the same program, due to random OS delays. But -it's not too bad, and it becomes less of a problem the longer a -program runs. - -Massif takes censuses at an appropriate timescale; censuses -take place less frequently as the program runs for longer. There -is no point having more than 100-200 censuses on a single -graph. - -The graphs give a good overview of where your program's -space use comes from, and how that varies over time. The -accompanying text/HTML file gives a lot more information about -heap use. + +The Output Preamble + +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: + + - + +The Output Graph +The next part is the graph that shows how memory consumption occurred +as the program executed: - -Details of Heap Allocations +ki + 0 121.8 + +Number of snapshots: 25 + Detailed snapshots: [9, 14 (peak), 24] +]]> + +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 execution +instructions involved the loading and dynamic linking of the program. The +execution of main (and thus the heap +allocations) only occur at the very end. For a short-running program like +this, we can use the --time-unit=B option +to specify that we want the time unit to instead be the number of bytes +allocated/deallocated on the heap and stack(s). + +If we re-run the program under Massif with this option, and then +re-run ms_print, we get this more useful graph: -The text/HTML file contains information to help interpret -the heap bands of the graph. It also contains a lot of extra -information about heap allocations that you don't see in the -graph. +KB + 0 29.48 + +Number of snapshots: 25 + Detailed snapshots: [9, 14 (peak), 24] +]]> + +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 +--max-snapshots option) half of them are +deleted. This means that a reasonable number of snapshots are always +maintained. + +Most snapshots are normal, and only basic +information is recorded for them. Normal snapshots are represented in the +graph by bars consisting of ':' and '.' characters. + +Some snapshots are detailed. 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 +--detailed-freqoption. + +Finally, there is at most one peak snapshot. The +peak snapshot is detailed, and records the point where memory consumption +was greatest. (Actually, 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 +--peak-inaccuracy option below for more +details.) The peak snapshot is represented in the graph by a bar consisting +of '#' and '.' characters. The text at the bottom show that snapshot 14 was +the peak. Note that for tiny programs that never deallocate heap memory, +Massif will record a peak snapshot. + +The following graph is from an execution of Konqueror, the KDE web +browser. It shows what graphs for larger programs look like. +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)] +]]> + +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. + -Here's part of the information that accompanies the above -graph. -
-== 0 =========================== + +The Snapshot Details -Heap allocation functions accounted for 50.8% of measured -spacetime +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: + + +Each normal snapshot records several things. -Called from: - - - 22.1%: 0x401767D0: - _nl_intern_locale_data (in /lib/i686/libc-2.3.2.so) - - - 8.6%: 0x4017C393: - read_alias_file (in /lib/i686/libc-2.3.2.so) - - - ... ... (several entries omitted) - - - and 6 other insignificant places - - -
- -The first part shows the total spacetime due to heap -allocations, and the places in the program where most memory was -allocated. If this program had been compiled with --g, actual line numbers would be -given. These places are sorted, from most significant to least, -and correspond to the bands seen in the graph. Insignificant -sites (accounting for less than 0.5% of total spacetime) are -omitted. - -That alone can be useful, but often isn't enough. What if -one of these functions was called from several different places -in the program? Which one of these is responsible for most of -the memory used? For -_nl_intern_locale_data(), this -question is answered by clicking on the -22.1% link, which takes us to the -following part of the file: - -
-== 1 =========================== - -Context accounted for 22.1% -of measured spacetime - - 0x401767D0: _nl_intern_locale_data (in -/lib/i686/libc-2.3.2.so) - -Called from: - - - 22.1%: 0x40176F95: - _nl_load_locale_from_archive (in - /lib/i686/libc-2.3.2.so) - - -
- -At this level, we can see all the places from which -_nl_load_locale_from_archive() -was called such that it allocated memory at 0x401767D0. (We can -click on the top 22.1% link to go back -to the parent entry.) At this level, we have moved beyond the -information presented in the graph. In this case, it is only -called from one place. We can again follow the link for more -detail, moving to the following part of the file. - -
-== 2 =========================== - -Context accounted for 22.1% of -measured spacetime - - 0x401767D0: _nl_intern_locale_data (in -/lib/i686/libc-2.3.2.so) -0x40176F95: _nl_load_locale_from_archive (in -/lib/i686/libc-2.3.2.so) - -Called from: - - 22.1%: 0x40176184: _nl_find_locale (in - /lib/i686/libc-2.3.2.so) - + Its number. + + The time it was taken. In this case, the time unit is + bytes, due to the use of + --time-unit=B. + + The total memory consumption at that point. + + The number of useful heap bytes allocated at that point. + This reflects the number of bytes asked for by the + program. + + 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. + + 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 + --heap-admin option. + + 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 suitable aligned. The rounding size can be changed + with the --alignment option, although it + cannot be less than 8, and must be a power of two. + + 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. -
- -In this way we can dig deeper into the call stack, to work -out exactly what sequence of calls led to some memory being -allocated. At this point, with a call depth of 3, the -information runs out (thus the address of the child entry, -0x40176184, isn't a link). We could rerun the program with a -greater --depth value if we -wanted more information. - -Sometimes you will get a code location like this: - - -The code address isn't really 0xFFFFFFFF -- that's -impossible. This is what Massif does when it can't work out what -the real code address is. -Massif produces this information in a plain text file by -default, or HTML with the ---format=html option. The plain -text version obviously doesn't have the links, but a similar -effect can be achieved by searching on the code addresses. In -the Vim editor, the '*' and '#' searches are ideal for this. +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: +99.21% (9,000B) 0x804841A: main (example.c:20) +]]> + +The allocation tree can be read from the top down. The first line +indicates all heap allocation functions such as malloc +and C++ new. 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 malloc and new +called? At this point, every allocation so far has been due to line 21 +inside main, hence the second line in the tree. The +-> indicates that main (line 20) called +malloc. + +Let's see what the subsequent output shows happened next: - -Accuracy - -The information should be pretty accurate. Some -approximations made might cause some allocation contexts to be -attributed with less memory than they actually allocated, but the -amounts should be miniscule. +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) +]]> + +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%). + +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. + +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. + +The final part of the output is similar: -The heap admin spacetime figure is an approximation, as -described above. If anyone knows how to improve its accuracy, -please let us know. +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%) +]]> + +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/ms_print only show the details for code locations +responsible for more than 1% of useful memory bytes. The entries that do +not meet this threshold are aggregated. This avoids filling up the output +with large numbers of unimportant entries. This threshold can be changed +with the --threshold option of both Massif +and ms_print. @@ -428,9 +480,7 @@ please let us know. - When enabled, profile heap usage in detail. Without it, the - massif.pid.txt or - massif.pid.html will be very short. + Specifies whether heap profiling should be done. @@ -439,12 +489,13 @@ please let us know. - The number of admin bytes per block to use. This can only - be an estimate of the average, since it may vary. The allocator - used by glibc 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 count this. + If heap profiling is on, 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 + glibc 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. @@ -453,22 +504,23 @@ please let us know. - When enabled, include stack(s) in the profile. Threaded - programs can have multiple stacks. + 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. - + - Depth of call chains to present in the detailed heap - information. Increasing it will give more information, but - massif will run the program more slowly, - using more memory, and produce a bigger - massif.pid.txt or - massif.pid.hp file. + 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. @@ -477,25 +529,131 @@ please let us know. - Specify a function that allocates memory. This is useful - for functions that are wrappers to malloc(), - which can fill up the context information uselessly (and give very - uninformative bands on the graph). Functions specified will be - ignored in contexts, i.e. treated as though they were - malloc(). This option can be specified - multiple times on the command line, to name multiple - functions. + Functions specified with this option will be treated as though + they were a heap allocation function such as + malloc. This is useful for functions that are + wrappers to malloc or new, + 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. + + 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: + + + + + The full list of functions and operators that are by default + considered allocation functions is as follows. + + + + + + + + + + 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. + + + + + + + + + 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 are 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. + + + + + + + + + The time unit used for the profiling. There are three + possibilities: instructions executed (i), which is good for most + cases; real time (ms, i.e. milliseconds), which is useful sometimes; + 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. + + + + + + + + + Frequency of detailed snapshots. With + --detailed-freq=1, every snapshot is + detailed. + + + + + + + + + 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. + + + + + + + + + Write the profile data to file + rather than to the default output file, + massif.out.<pid>. The + and 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 + . See here for details. + - + - + - Produce the detailed heap information in text or HTML - format. The file suffix used will be either - .txt or .html. + The minimum alignment (and thus size) of heap blocks. @@ -504,4 +662,49 @@ please let us know. + + +ms_print Options + +ms_print's options are: + + + + + -h, --help + -v, --version + Help and version, as usual. + + + + [default: 1.0] + Same as Massif's --threshold, but + applied after profiling rather than during. + + + + [default: 72] + Width of the graph, in columns. + + + + [default: 20] + Height of the graph, in rows. + + + + + + + +Massif's output file format +Massif's file format is plain text (i.e. not binary) and deliberately +easy to read for both humands 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. + + +
diff --git a/massif/ms_main.c b/massif/ms_main.c index f940a91440..660a7188b7 100644 --- a/massif/ms_main.c +++ b/massif/ms_main.c @@ -31,13 +31,11 @@ // XXX: //--------------------------------------------------------------------------- // Todo -- critical for release: -// - write documentation // - address/close all the bug reports below (after writing docs) // - do a graph-drawing test -// - write a good basic test that shows how the tool works, suitable for -// documentation -// - In cg_annotate, remove the -- option. // - Get Josef to update the Callgrind --callgrind-out-file option. +// - Use '_' instead of '.' for detailed/peak bars? +// - ms_print -- XXX on line 535 // // Todo -- nice, but less critical: // - make file format more generic. Obstacles: @@ -57,6 +55,10 @@ // identified? [hmm, could make getting the name of alloc-fns more // difficult] [could dump full names to file, truncate in ms_print] // - make --show-below-main=no work +// - Options like --alloc-fn='operator new(unsigned, std::nothrow_t const&)' +// don't work in a .valgrindrc file or in $VALGRIND_OPTS. +// m_commandline.c:add_args_from_string() needs to respect single quotes. +// // // Performance: // - To run the benchmarks: @@ -80,8 +82,6 @@ // VG_(bsearch) function. // // Todo -- low priority: -// - Consider 'instructions executed' as a time unit -- more regular than -// ms, less artificial than B (bug #121629). // - In each XPt, record both bytes and the number of allocations, and // possibly the global number of allocations. // - (Artur Wisz) add a feature to Massif to ignore any heap blocks larger @@ -297,6 +297,10 @@ static UInt n_XCon_redos = 0; //--- Globals ---// //------------------------------------------------------------// +// Number of guest instructions executed so far. Only used with +// --time-unit=i. +static Long guest_instrs_executed = 0; + static SizeT heap_szB = 0; // Live heap size static SizeT heap_extra_szB = 0; // Live heap extra size -- slop + admin bytes static SizeT stacks_szB = 0; // Live stacks size @@ -377,11 +381,12 @@ static Bool is_alloc_fn(Char* fnname) #define MAX_DEPTH 200 -typedef enum { TimeMS, TimeB } TimeUnit; +typedef enum { TimeI, TimeMS, TimeB } TimeUnit; static Char* TimeUnit_to_string(TimeUnit time_unit) { switch (time_unit) { + case TimeI: return "i"; case TimeMS: return "ms"; case TimeB: return "B"; default: tl_assert2(0, "TimeUnit_to_string: unrecognised TimeUnit"); @@ -398,7 +403,7 @@ static Bool clo_stacks = False; static UInt clo_depth = 30; static double clo_threshold = 1.0; // percentage static double clo_peak_inaccuracy = 1.0; // percentage -static UInt clo_time_unit = TimeMS; +static UInt clo_time_unit = TimeI; static UInt clo_detailed_freq = 10; static UInt clo_max_snapshots = 100; static Char* clo_massif_out_file = "massif.out.%p"; @@ -413,7 +418,6 @@ static Bool ms_process_cmd_line_option(Char* arg) VG_BOOL_CLO(arg, "--heap", clo_heap) else VG_BOOL_CLO(arg, "--stacks", clo_stacks) - // XXX: "--heap-admin= " is accepted! else VG_NUM_CLO(arg, "--heap-admin", clo_heap_admin) else VG_NUM_CLO(arg, "--depth", clo_depth) @@ -424,6 +428,7 @@ static Bool ms_process_cmd_line_option(Char* arg) else VG_NUM_CLO(arg, "--detailed-freq", clo_detailed_freq) else VG_NUM_CLO(arg, "--max-snapshots", clo_max_snapshots) + else if (VG_CLO_STREQ(arg, "--time-unit=i")) clo_time_unit = TimeI; else if (VG_CLO_STREQ(arg, "--time-unit=ms")) clo_time_unit = TimeMS; else if (VG_CLO_STREQ(arg, "--time-unit=B")) clo_time_unit = TimeB; @@ -446,15 +451,15 @@ static void ms_print_usage(void) { VG_(printf)( " --heap=no|yes profile heap blocks [yes]\n" -" --heap-admin= average admin bytes per heap block;" +" --heap-admin= average admin bytes per heap block;\n" " ignored if --heap=no [8]\n" " --stacks=no|yes profile stack(s) [no]\n" " --depth= depth of contexts [30]\n" " --alloc-fn= specify as an alloc function [empty]\n" " --threshold= significance threshold, as a percentage [1.0]\n" " --peak-inaccuracy= maximum peak inaccuracy, as a percentage [1.0]\n" -" --time-unit=ms|B time unit, milliseconds or bytes\n" -" alloc'd/dealloc'd on the heap [ms]\n" +" --time-unit=i|ms|B time unit: instructions executed, milliseconds\n" +" or heap bytes alloc'd/dealloc'd [i]\n" " --detailed-freq= every Nth snapshot should be detailed [10]\n" " --max-snapshots= maximum number of snapshots recorded [100]\n" " --massif-out-file= output file name [massif.out.%%p]\n" @@ -963,7 +968,7 @@ static void update_XCon(XPt* xpt, SSizeT space_delta) // limit again, we again cull and then take them even more slowly, and so // on. -// Time is measured either in ms or bytes, depending on the --time-unit +// Time is measured either in i or ms or bytes, depending on the --time-unit // option. It's a Long because it can exceed 32-bits reasonably easily, and // because we need to allow negative values to represent unset times. typedef Long Time; @@ -1227,7 +1232,9 @@ static UInt cull_snapshots(void) static Time get_time(void) { // Get current time, in whatever time unit we're using. - if (clo_time_unit == TimeMS) { + if (clo_time_unit == TimeI) { + return guest_instrs_executed; + } else if (clo_time_unit == TimeMS) { // Some stuff happens between the millisecond timer being initialised // to zero and us taking our first snapshot. We determine that time // gap so we can subtract it from all subsequent times so that our @@ -1774,9 +1781,74 @@ static Bool ms_handle_client_request ( ThreadId tid, UWord* argv, UWord* ret ) //--- Instrumentation ---// //------------------------------------------------------------// +static void add_counter_update(IRSB* sbOut, Int n) +{ + #if defined(VG_BIGENDIAN) + # define END Iend_BE + #elif defined(VG_LITTLEENDIAN) + # define END Iend_LE + #else + # error "Unknown endianness" + #endif + // Add code to increment 'guest_instrs_executed' by 'n', like this: + // WrTmp(t1, Load64(&guest_instrs_executed)) + // WrTmp(t2, Add64(RdTmp(t1), Const(n))) + // Store(&guest_instrs_executed, t2) + IRTemp t1 = newIRTemp(sbOut->tyenv, Ity_I64); + IRTemp t2 = newIRTemp(sbOut->tyenv, Ity_I64); + IRExpr* counter_addr = mkIRExpr_HWord( (HWord)&guest_instrs_executed ); + + IRStmt* st1 = IRStmt_WrTmp(t1, IRExpr_Load(END, Ity_I64, counter_addr)); + IRStmt* st2 = + IRStmt_WrTmp(t2, + IRExpr_Binop(Iop_Add64, IRExpr_RdTmp(t1), + IRExpr_Const(IRConst_U64(n)))); + IRStmt* st3 = IRStmt_Store(END, counter_addr, IRExpr_RdTmp(t2)); + + addStmtToIRSB( sbOut, st1 ); + addStmtToIRSB( sbOut, st2 ); + addStmtToIRSB( sbOut, st3 ); +} + +static IRSB* ms_instrument2( IRSB* sbIn ) +{ + Int i, n = 0; + IRSB* sbOut; + + // We increment the instruction count in two places: + // - just before any Ist_Exit statements; + // - just before the IRSB's end. + // In the former case, we zero 'n' and then continue instrumenting. + + sbOut = deepCopyIRSBExceptStmts(sbIn); + + for (i = 0; i < sbIn->stmts_used; i++) { + IRStmt* st = sbIn->stmts[i]; + + if (!st || st->tag == Ist_NoOp) continue; + + if (st->tag == Ist_IMark) { + n++; + } else if (st->tag == Ist_Exit) { + if (n > 0) { + // Add an increment before the Exit statement, then reset 'n'. + add_counter_update(sbOut, n); + n = 0; + } + } + addStmtToIRSB( sbOut, st ); + } + + if (n > 0) { + // Add an increment before the SB end. + add_counter_update(sbOut, n); + } + return sbOut; +} + static IRSB* ms_instrument ( VgCallbackClosure* closure, - IRSB* bb_in, + IRSB* sbIn, VexGuestLayout* layout, VexGuestExtents* vge, IRType gWordTy, IRType hWordTy ) @@ -1788,7 +1860,11 @@ IRSB* ms_instrument ( VgCallbackClosure* closure, have_started_executing_code = True; maybe_take_snapshot(Normal, "startup"); } - return bb_in; + + if (clo_time_unit == TimeI) { return ms_instrument2(sbIn); } + else if (clo_time_unit == TimeMS) { return sbIn; } + else if (clo_time_unit == TimeB) { return sbIn; } + else { tl_assert2(0, "bad --time-unit value"); } } @@ -1816,7 +1892,7 @@ static Char* make_perc(ULong x, ULong y) // tl_assert(x <= y); XXX; put back in later... -// XXX: I'm not confident that VG_(percentify) works as it should... + // XXX: I'm not confident that VG_(percentify) works as it should... VG_(percentify)(x, y, 2, 6, mbuf); // XXX: this is bogus if the denominator was zero -- resulting string is // something like "0 --%") @@ -2103,7 +2179,7 @@ static void ms_pre_clo_init(void) { VG_(details_name) ("Massif"); VG_(details_version) (NULL); - VG_(details_description) ("a space profiler"); + VG_(details_description) ("a heap profiler"); VG_(details_copyright_author)( "Copyright (C) 2003-2007, and GNU GPL'd, by Nicholas Nethercote"); VG_(details_bug_reports_to) (VG_BUGS_TO); diff --git a/massif/ms_print.in b/massif/ms_print.in index 95a6e8cd45..4b13f3c705 100755 --- a/massif/ms_print.in +++ b/massif/ms_print.in @@ -275,6 +275,27 @@ sub max_label_2($$) else { return sprintf("%5.1f", $szB_scaled); } } +# Work out the units for the max value, measured in instructions. +sub i_max_label($) +{ + my ($nI) = @_; + + # We repeat until the number is less than 1000. + my $nI_scaled = $nI; + my $unit = "i"; + # Nb: 'k' is the "kilo" (1000) prefix. + if ($nI_scaled >= 1000) { $unit = "ki"; $nI_scaled /= 1024; } + if ($nI_scaled >= 1000) { $unit = "Mi"; $nI_scaled /= 1024; } + if ($nI_scaled >= 1000) { $unit = "Gi"; $nI_scaled /= 1024; } + if ($nI_scaled >= 1000) { $unit = "Ti"; $nI_scaled /= 1024; } + if ($nI_scaled >= 1000) { $unit = "Pi"; $nI_scaled /= 1024; } + if ($nI_scaled >= 1000) { $unit = "Ei"; $nI_scaled /= 1024; } + if ($nI_scaled >= 1000) { $unit = "Zi"; $nI_scaled /= 1024; } + if ($nI_scaled >= 1000) { $unit = "Yi"; $nI_scaled /= 1024; } + + return (max_label_2($nI, $nI_scaled), $unit); +} + # Work out the units for the max value, measured in bytes. sub B_max_label($) { @@ -284,6 +305,9 @@ sub B_max_label($) # each scaling. my $szB_scaled = $szB; my $unit = "B"; + # Nb: 'K' or 'k' are acceptable as the "binary kilo" (1024) prefix. + # (Strictly speaking, should use "KiB" (kibibyte), "MiB" (mebibyte), etc, + # but they're not in common use.) if ($szB_scaled >= 1000) { $unit = "KB"; $szB_scaled /= 1024; } if ($szB_scaled >= 1000) { $unit = "MB"; $szB_scaled /= 1024; } if ($szB_scaled >= 1000) { $unit = "GB"; $szB_scaled /= 1024; } @@ -508,6 +532,7 @@ sub read_input_file() if (0 == $end_time ) { $end_time = 1; } my $K = $peak_mem_total_szB / $graph_y; +# XXX: remove this? see 10 lines down... # If we leave end_time as is, the final snapshot will spill over past # the last column. So we add a small epsilon to it to prevent this from # happening. @@ -533,9 +558,9 @@ sub read_input_file() # detailed column. my $should_draw_column = (($i == $peak_num) or - ($is_detaileds[$i] and $graph[$x][0] ne $peak_full_char) or - ($graph[$x][0] ne $peak_full_char and - $graph[$x][0] ne $detailed_full_char)); + ($is_detaileds[$i] and $graph[$x][1] ne $peak_full_char) or + ($graph[$x][1] ne $peak_full_char and + $graph[$x][1] ne $detailed_full_char)); if ($should_draw_column) { # If it's detailed, mark the X-axis. Also choose the full-slot @@ -543,10 +568,8 @@ sub read_input_file() my $full_char; if ($i == $peak_num) { $full_char = $peak_full_char; - $graph[$x][0] = $full_char; } elsif ($is_detaileds[$i]) { $full_char = $detailed_full_char; - $graph[$x][0] = $full_char; } else { $full_char = $normal_full_char; } @@ -566,9 +589,11 @@ sub read_input_file() # Print graph[][]. #------------------------------------------------------------------------- my ($y_label, $y_unit) = B_max_label($peak_mem_total_szB); - my ($x_label, $x_unit) = ( $time_unit eq "ms" - ? t_max_label($end_time) - : B_max_label($end_time) ); + my ($x_label, $x_unit); + if ($time_unit eq "i") { ($x_label, $x_unit) = i_max_label($end_time) } + elsif ($time_unit eq "s") { ($x_label, $x_unit) = t_max_label($end_time) } + elsif ($time_unit eq "B") { ($x_label, $x_unit) = B_max_label($end_time) } + else { die "bad time_unit: $time_unit\n"; } printf(" %2s\n", $y_unit); for ($y = $graph_y; $y >= 0; $y--) { @@ -612,7 +637,7 @@ sub read_input_file() } } } - print("]\n"); + print("]\n\n"); #------------------------------------------------------------------------- # Print snapshots, from $tmp_file. diff --git a/massif/tests/Makefile.am b/massif/tests/Makefile.am index 3f54d4508e..97802683b9 100644 --- a/massif/tests/Makefile.am +++ b/massif/tests/Makefile.am @@ -8,6 +8,7 @@ EXTRA_DIST = $(noinst_SCRIPTS) \ alloc-fns-A.post.exp alloc-fns-A.stderr.exp alloc-fns-A.vgtest \ alloc-fns-B.post.exp alloc-fns-B.stderr.exp alloc-fns-B.vgtest \ basic.post.exp basic.stderr.exp basic.vgtest \ + basic2.post.exp basic2.stderr.exp basic2.vgtest \ insig.post.exp insig.stderr.exp insig.vgtest \ big-alloc.post.exp big-alloc.stderr.exp big-alloc.vgtest \ deep-A.post.exp deep-A.stderr.exp deep-A.vgtest \ diff --git a/massif/tests/alloc-fns-A.post.exp b/massif/tests/alloc-fns-A.post.exp index 9a21059add..20b43ca42d 100644 --- a/massif/tests/alloc-fns-A.post.exp +++ b/massif/tests/alloc-fns-A.post.exp @@ -26,11 +26,12 @@ ms_print arguments: massif.out | : : : : : : : @ | : : : : : : : : @ | : : : : : : : : @ - 0 +-----------------------------------------------------------------------@KB + 0 +----------------------------------------------------------------------->KB 0 1.758 Number of snapshots: 10 Detailed snapshots: [9] + -------------------------------------------------------------------------------- n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- diff --git a/massif/tests/alloc-fns-B.post.exp b/massif/tests/alloc-fns-B.post.exp index 3712260d59..bb1c6e9f65 100644 --- a/massif/tests/alloc-fns-B.post.exp +++ b/massif/tests/alloc-fns-B.post.exp @@ -26,11 +26,12 @@ ms_print arguments: massif.out | : : : : : : : @ | : : : : : : : : @ | : : : : : : : : @ - 0 +-----------------------------------------------------------------------@KB + 0 +----------------------------------------------------------------------->KB 0 1.758 Number of snapshots: 10 Detailed snapshots: [9] + -------------------------------------------------------------------------------- n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- diff --git a/massif/tests/basic.post.exp b/massif/tests/basic.post.exp index 8cda5873f7..fbc8286140 100644 --- a/massif/tests/basic.post.exp +++ b/massif/tests/basic.post.exp @@ -26,11 +26,12 @@ ms_print arguments: massif.out | .:::@:::::::::@:::::::::@::::::#:::::::::@:::::::::@:::::::::@. | .:::::@:::::::::@:::::::::@::::::#:::::::::@:::::::::@:::::::::@::. | .:::::::@:::::::::@:::::::::@::::::#:::::::::@:::::::::@:::::::::@::::. - 0 +---------@---------@---------@------#---------@---------@---------@---->KB + 0 +----------------------------------------------------------------------->KB 0 14.42 Number of snapshots: 73 Detailed snapshots: [9, 19, 29, 37 (peak), 47, 57, 67] + -------------------------------------------------------------------------------- n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- diff --git a/massif/tests/basic2.post.exp b/massif/tests/basic2.post.exp new file mode 100644 index 0000000000..f926c7af30 --- /dev/null +++ b/massif/tests/basic2.post.exp @@ -0,0 +1,96 @@ +-------------------------------------------------------------------------------- +Command: ./basic +Massif arguments: --stacks=no --time-unit=B --massif-out-file=massif.out --detailed-freq=1 --max-snapshots=10 +ms_print arguments: massif.out +-------------------------------------------------------------------------------- + + + KB +7.312^ # + | # + | # + | # + | # . + | @ # @ + | @ # @ + | @ # @ + | @ # @ + | . @ # @ @ + | @ @ # @ @ + | @ @ # @ @ + | @ @ # @ @ + | @ @ # @ @ . + | @ @ # @ @ @ + | @ @ @ # @ @ @ + | @ @ @ # @ @ @ + | @ @ @ # @ @ @ + | @ @ @ # @ @ @ @ + | @ @ @ # @ @ @ @ + 0 +----------------------------------------------------------------------->KB + 0 13.81 + +Number of snapshots: 9 + Detailed snapshots: [0, 1, 2, 3, 4 (peak), 5, 6, 7, 8] + +-------------------------------------------------------------------------------- + n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) +-------------------------------------------------------------------------------- + 0 0 0 0 0 0 +00.00% (0B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc. + +-------------------------------------------------------------------------------- + n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) +-------------------------------------------------------------------------------- + 1 1,872 1,872 1,800 72 0 +96.15% (1,800B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc. +->96.15% (1,800B) 0x........: main (basic.c:14) + +-------------------------------------------------------------------------------- + n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) +-------------------------------------------------------------------------------- + 2 3,952 3,952 3,800 152 0 +96.15% (3,800B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc. +->96.15% (3,800B) 0x........: main (basic.c:14) + +-------------------------------------------------------------------------------- + n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) +-------------------------------------------------------------------------------- + 3 5,616 5,616 5,400 216 0 +96.15% (5,400B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc. +->96.15% (5,400B) 0x........: main (basic.c:14) + +-------------------------------------------------------------------------------- + n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) +-------------------------------------------------------------------------------- + 4 7,488 7,488 7,200 288 0 +96.15% (7,200B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc. +->96.15% (7,200B) 0x........: main (basic.c:14) + +-------------------------------------------------------------------------------- + n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) +-------------------------------------------------------------------------------- + 5 9,152 5,824 5,600 224 0 +96.15% (5,600B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc. +->96.15% (5,600B) 0x........: main (basic.c:14) + +-------------------------------------------------------------------------------- + n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) +-------------------------------------------------------------------------------- + 6 10,816 4,160 4,000 160 0 +96.15% (4,000B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc. +->96.15% (4,000B) 0x........: main (basic.c:14) + +-------------------------------------------------------------------------------- + n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) +-------------------------------------------------------------------------------- + 7 12,480 2,496 2,400 96 0 +96.15% (2,400B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc. +->96.15% (2,400B) 0x........: main (basic.c:14) + +-------------------------------------------------------------------------------- + n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) +-------------------------------------------------------------------------------- + 8 14,144 832 800 32 0 +96.15% (800B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc. +->96.15% (800B) 0x........: main (basic.c:14) + diff --git a/massif/tests/basic2.stderr.exp b/massif/tests/basic2.stderr.exp new file mode 100644 index 0000000000..139597f9cb --- /dev/null +++ b/massif/tests/basic2.stderr.exp @@ -0,0 +1,2 @@ + + diff --git a/massif/tests/basic2.vgtest b/massif/tests/basic2.vgtest new file mode 100644 index 0000000000..e9d1de43ac --- /dev/null +++ b/massif/tests/basic2.vgtest @@ -0,0 +1,4 @@ +prog: basic +vgopts: --stacks=no --time-unit=B --massif-out-file=massif.out --detailed-freq=1 --max-snapshots=10 +post: perl ../../massif/ms_print massif.out | ../../tests/filter_addresses +cleanup: rm massif.out diff --git a/massif/tests/big-alloc.post.exp b/massif/tests/big-alloc.post.exp index 75c4d34fc3..af84e2a04c 100644 --- a/massif/tests/big-alloc.post.exp +++ b/massif/tests/big-alloc.post.exp @@ -26,11 +26,12 @@ ms_print arguments: massif.out | : : : : : : : @ : | : : : : : : : : @ : | : : : : : : : : @ : - 0 +----------------------------------------------------------------@------>MB + 0 +----------------------------------------------------------------------->MB 0 100.0 Number of snapshots: 11 Detailed snapshots: [9] + -------------------------------------------------------------------------------- n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- diff --git a/massif/tests/custom_alloc.post.exp b/massif/tests/custom_alloc.post.exp index 8fcc672bb9..567534f41f 100644 --- a/massif/tests/custom_alloc.post.exp +++ b/massif/tests/custom_alloc.post.exp @@ -26,11 +26,12 @@ ms_print arguments: massif.out | @ # : : | @ # : : | @ # : : - 0 +------@----------------#----------------------------------------------->KB + 0 +----------------------------------------------------------------------->KB 0 1.242 Number of snapshots: 11 Detailed snapshots: [2, 5 (peak)] + -------------------------------------------------------------------------------- n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- diff --git a/massif/tests/deep-A.post.exp b/massif/tests/deep-A.post.exp index c84218a5e8..493afdf6e4 100644 --- a/massif/tests/deep-A.post.exp +++ b/massif/tests/deep-A.post.exp @@ -26,11 +26,12 @@ ms_print arguments: massif.out | : : : : : : : @ : | : : : : : : : : @ : | : : : : : : : : @ : - 0 +----------------------------------------------------------------@------>KB + 0 +----------------------------------------------------------------------->KB 0 2.031 Number of snapshots: 11 Detailed snapshots: [9] + -------------------------------------------------------------------------------- n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- diff --git a/massif/tests/deep-B.post.exp b/massif/tests/deep-B.post.exp index 2e4ceed245..e3e3efe947 100644 --- a/massif/tests/deep-B.post.exp +++ b/massif/tests/deep-B.post.exp @@ -26,11 +26,12 @@ ms_print arguments: massif.out | : : : : : : : @ : | : : : : : : : : @ : | : : : : : : : : @ : - 0 +----------------------------------------------------------------@------>KB + 0 +----------------------------------------------------------------------->KB 0 2.031 Number of snapshots: 11 Detailed snapshots: [9] + -------------------------------------------------------------------------------- n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- diff --git a/massif/tests/deep-C.post.exp b/massif/tests/deep-C.post.exp index 06f2a68253..fc12a5a484 100644 --- a/massif/tests/deep-C.post.exp +++ b/massif/tests/deep-C.post.exp @@ -26,11 +26,12 @@ ms_print arguments: massif.out | : : : : : : : @ : | : : : : : : : : @ : | : : : : : : : : @ : - 0 +----------------------------------------------------------------@------>KB + 0 +----------------------------------------------------------------------->KB 0 2.031 Number of snapshots: 11 Detailed snapshots: [9] + -------------------------------------------------------------------------------- n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- diff --git a/massif/tests/deep-D.post.exp b/massif/tests/deep-D.post.exp index b5da9226f6..5d47fe55fb 100644 --- a/massif/tests/deep-D.post.exp +++ b/massif/tests/deep-D.post.exp @@ -26,11 +26,12 @@ ms_print arguments: massif.out | : : : : : : : @ : | : : : : : : : : @ : | : : : : : : : : @ : - 0 +----------------------------------------------------------------@------>KB + 0 +----------------------------------------------------------------------->KB 0 2.031 Number of snapshots: 11 Detailed snapshots: [9] + -------------------------------------------------------------------------------- n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- diff --git a/massif/tests/filter_stderr b/massif/tests/filter_stderr index 793b158f96..e9d50df8d9 100755 --- a/massif/tests/filter_stderr +++ b/massif/tests/filter_stderr @@ -5,5 +5,5 @@ dir=`dirname $0` $dir/../../tests/filter_stderr_basic | # Remove "Massif, ..." line and the following copyright line. -sed "/^Massif, a space profiler./ , /./ d" +sed "/^Massif, a heap profiler./ , /./ d" diff --git a/massif/tests/ignoring.post.exp b/massif/tests/ignoring.post.exp index e21b19e34a..efe7c09214 100644 --- a/massif/tests/ignoring.post.exp +++ b/massif/tests/ignoring.post.exp @@ -26,11 +26,12 @@ ms_print arguments: massif.out |# @:::@:::::::::::::::@:::@:::@:::@:::@: ::@:::::::@:::::::@:::::::@:::: |# @:::@:::::::::::::::@:::@:::@:::@:::@: ::@:::::::@:::::::@:::::::@:::: |# @:::@:::::::::::::::@:::@:::@:::@:::@: ::@:::::::@:::::::@:::::::@:::: - 0 +#-@---@---------------@---@---@---@---@----@-------@-------@-------@--->KB + 0 +----------------------------------------------------------------------->KB 0 182.7 Number of snapshots: 88 Detailed snapshots: [1 (peak), 3, 8, 26, 31, 36, 41, 46, 52, 62, 72, 82] + -------------------------------------------------------------------------------- n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- diff --git a/massif/tests/insig.post.exp b/massif/tests/insig.post.exp index b1e5160acf..e71fee1567 100644 --- a/massif/tests/insig.post.exp +++ b/massif/tests/insig.post.exp @@ -26,11 +26,12 @@ ms_print arguments: massif.out | : ::::@::::@:: | : ::::@::::@:: | : ::::@::::@:: - 0 +----------------------------------------------------------------@----@->KB + 0 +----------------------------------------------------------------------->KB 0 9.617 Number of snapshots: 24 Detailed snapshots: [9, 19] + -------------------------------------------------------------------------------- n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- diff --git a/massif/tests/long-time.post.exp b/massif/tests/long-time.post.exp index 80e91638ae..298f5677b3 100644 --- a/massif/tests/long-time.post.exp +++ b/massif/tests/long-time.post.exp @@ -6,31 +6,32 @@ ms_print arguments: massif.out MB -2.193^#: : : @ : : - |#: : : @ : : - |#: : : @ : : - |#: :. :. . @. :. . - |#: :: :: : @: :@ : - |#: :: :: : @: :@ : - |#: :: :: : @: :@ : - |#: :: :: : @: :@ : - |#: :: :: : @: :@ : - |#: :: :: : @: :@ : - |#: :: :: : @: :@ : :. :. :. :. :. :. :. . :. :. :. : - |#: :: :: : @: :@ : :: :: :: :: :@ :: :: : :: :@ :: : - |#:..................:: :: : @: :@ : ::.::.::.:: :@ :: :: .: :: :@ :: : - |#::::@:::::::::::::::: :: : @: :@ : :::::@:::::.:@.::.::.@:.::.:@.::.: - |#::::@:::::::::::::::: :: : @: :@ : :::::@:::::::@:::::::@::::::@::::: - |#::::@:::::::::::::::: :: : @: :@ : :::::@:::::::@:::::::@::::::@::::: - |#::::@:::::::::::::::: :: : @: :@ : :::::@:::::::@:::::::@::::::@::::: - |#::::@:::::::::::::::: :: : @: :@ : :::::@:::::::@:::::::@::::::@::::: - |#::::@:::::::::::::::: :: : @: :@ : :::::@:::::::@:::::::@::::::@::::: - |#::::@:::::::::::::::: :: : @: :@ : :::::@:::::::@:::::::@::::::@::::: - 0 +#----@----------------@---@--@---@---@-----@-------@-------@------@---->GB +2.193^#: : : : @ : : + |#: : : : @ : : + |#: : : : @ : : + |#: :. :. :. @. :. . + |#: :: :: :: @: :@ : + |#: :: :: :: @: :@ : + |#: :: :: :: @: :@ : + |#: :: :: :: @: :@ : + |#: :: :: :: @: :@ : + |#: :: :: :: @: :@ : + |#: :: :: :: @: :@ : :. :. :. :. :. :. :. . :. :. :. : + |#: :: :: :: @: :@ : :: :: :: :: :@ :: :: : :: :@ :: : + |#:..................:: :: :: @: :@ : ::.::.::.:: :@ :: :: .: :: :@ :: : + |#::::@:::::::::::::::: :: :: @: :@ : :::::@:::::.:@.::.::.@:.::.:@.::.: + |#::::@:::::::::::::::: :: :: @: :@ : :::::@:::::::@:::::::@::::::@::::: + |#::::@:::::::::::::::: :: :: @: :@ : :::::@:::::::@:::::::@::::::@::::: + |#::::@:::::::::::::::: :: :: @: :@ : :::::@:::::::@:::::::@::::::@::::: + |#::::@:::::::::::::::: :: :: @: :@ : :::::@:::::::@:::::::@::::::@::::: + |#::::@:::::::::::::::: :: :: @: :@ : :::::@:::::::@:::::::@::::::@::::: + |#::::@:::::::::::::::: :: :: @: :@ : :::::@:::::::@:::::::@::::::@::::: + 0 +----------------------------------------------------------------------->GB 0 11.15 Number of snapshots: 94 Detailed snapshots: [1 (peak), 7, 28, 33, 38, 43, 48, 56, 66, 76, 86] + -------------------------------------------------------------------------------- n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- diff --git a/massif/tests/new-cpp.post.exp b/massif/tests/new-cpp.post.exp index 31ecbb34ee..ce38885678 100644 --- a/massif/tests/new-cpp.post.exp +++ b/massif/tests/new-cpp.post.exp @@ -26,11 +26,12 @@ ms_print arguments: massif.out | : : : # : : : | : : : # : : : | : : : # : : : - 0 +-----------------------------------#----------------------------------->KB + 0 +----------------------------------------------------------------------->KB 0 23.50 Number of snapshots: 10 Detailed snapshots: [5 (peak)] + -------------------------------------------------------------------------------- n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- diff --git a/massif/tests/no-stack-no-heap.post.exp b/massif/tests/no-stack-no-heap.post.exp index 553e37ec1b..b8caf841a4 100644 --- a/massif/tests/no-stack-no-heap.post.exp +++ b/massif/tests/no-stack-no-heap.post.exp @@ -31,6 +31,7 @@ ms_print arguments: massif.out Number of snapshots: 1 Detailed snapshots: [] + -------------------------------------------------------------------------------- n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- diff --git a/massif/tests/null.post.exp b/massif/tests/null.post.exp index 332b2bf502..b02f5e7c7d 100644 --- a/massif/tests/null.post.exp +++ b/massif/tests/null.post.exp @@ -31,6 +31,7 @@ ms_print arguments: massif.out Number of snapshots: 1 Detailed snapshots: [] + -------------------------------------------------------------------------------- n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- diff --git a/massif/tests/one.post.exp b/massif/tests/one.post.exp index a57a4f4c82..6b7fec26ff 100644 --- a/massif/tests/one.post.exp +++ b/massif/tests/one.post.exp @@ -31,6 +31,7 @@ ms_print arguments: massif.out Number of snapshots: 2 Detailed snapshots: [] + -------------------------------------------------------------------------------- n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- diff --git a/massif/tests/overloaded-new.post.exp b/massif/tests/overloaded-new.post.exp index bdabf1d8cf..179ef2979a 100644 --- a/massif/tests/overloaded-new.post.exp +++ b/massif/tests/overloaded-new.post.exp @@ -26,11 +26,12 @@ ms_print arguments: massif.out | : : : # : : : | : : : # : : : | : : : # : : : - 0 +-----------------------------------#----------------------------------->KB + 0 +----------------------------------------------------------------------->KB 0 23.50 Number of snapshots: 10 Detailed snapshots: [5 (peak)] + -------------------------------------------------------------------------------- n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- diff --git a/massif/tests/peak.post.exp b/massif/tests/peak.post.exp index d3bd30c9aa..89d207e58f 100644 --- a/massif/tests/peak.post.exp +++ b/massif/tests/peak.post.exp @@ -26,11 +26,12 @@ ms_print arguments: massif.out | @ :@ @ @ @: @ :@ @ @ @: @ :@ @ @ @: @ :@ # | @. @ :@ @ @ @: @ :@ @ @ @: @ :@ @ @ @: @ :@ # | @ @: @ :@ @ @ @: @ :@ @ @ @: @ :@ @ @ @: @ :@ # - 0 +---@--@---@---@--@---@--@---@---@--@---@--@---@---@--@---@--@---@---@--#KB + 0 +----------------------------------------------------------------------->KB 0 19.69 Number of snapshots: 81 Detailed snapshots: [3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63, 67, 71, 75, 79 (peak)] + -------------------------------------------------------------------------------- n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- diff --git a/massif/tests/peak2.post.exp b/massif/tests/peak2.post.exp index f40f6f78ba..3e9cee60bc 100644 --- a/massif/tests/peak2.post.exp +++ b/massif/tests/peak2.post.exp @@ -26,11 +26,12 @@ ms_print arguments: massif.out | @ :@ @ @ @: @ :@ @ : @: : :@ : @ :: @ :: # | @. @ :@ @ @ @: @ :@ @ : @: : :@ : @ :: @ :: # | @ @: @ :@ @ @ @: @ :@ @ : @: : :@ : @ :: @ :: # - 0 +---@--@---@---@--@---@--@---@---@--@------@-------@------@------@------#KB + 0 +----------------------------------------------------------------------->KB 0 19.69 Number of snapshots: 76 Detailed snapshots: [3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 46, 53, 60, 67, 74 (peak)] + -------------------------------------------------------------------------------- n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- diff --git a/massif/tests/realloc.post.exp b/massif/tests/realloc.post.exp index 3c14c5b612..fc0a7fb8f3 100644 --- a/massif/tests/realloc.post.exp +++ b/massif/tests/realloc.post.exp @@ -26,11 +26,12 @@ ms_print arguments: --threshold=0 massif.out | @ # | @ # | @ # - 0 +-----------------------@-----------#----------------------------------->KB + 0 +----------------------------------------------------------------------->KB 0 1.172 Number of snapshots: 8 Detailed snapshots: [3, 6 (peak)] + -------------------------------------------------------------------------------- n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- diff --git a/massif/tests/thresholds_0_0.post.exp b/massif/tests/thresholds_0_0.post.exp index 07c444e087..ae2bef918b 100644 --- a/massif/tests/thresholds_0_0.post.exp +++ b/massif/tests/thresholds_0_0.post.exp @@ -26,11 +26,12 @@ ms_print arguments: massif.out --threshold=0 | : : ::: : @ | : : ::: : @ | : : ::: : @ - 0 +-----------------------------------------------------------------------@KB + 0 +----------------------------------------------------------------------->KB 0 39.06 Number of snapshots: 10 Detailed snapshots: [9] + -------------------------------------------------------------------------------- n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- diff --git a/massif/tests/thresholds_0_10.post.exp b/massif/tests/thresholds_0_10.post.exp index 550aa20db6..ab33bd744e 100644 --- a/massif/tests/thresholds_0_10.post.exp +++ b/massif/tests/thresholds_0_10.post.exp @@ -26,11 +26,12 @@ ms_print arguments: massif.out --threshold=10 | : : ::: : @ | : : ::: : @ | : : ::: : @ - 0 +-----------------------------------------------------------------------@KB + 0 +----------------------------------------------------------------------->KB 0 39.06 Number of snapshots: 10 Detailed snapshots: [9] + -------------------------------------------------------------------------------- n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- diff --git a/massif/tests/thresholds_10_0.post.exp b/massif/tests/thresholds_10_0.post.exp index 4ff75317e9..53d71e792a 100644 --- a/massif/tests/thresholds_10_0.post.exp +++ b/massif/tests/thresholds_10_0.post.exp @@ -26,11 +26,12 @@ ms_print arguments: massif.out --threshold=0 | : : ::: : @ | : : ::: : @ | : : ::: : @ - 0 +-----------------------------------------------------------------------@KB + 0 +----------------------------------------------------------------------->KB 0 39.06 Number of snapshots: 10 Detailed snapshots: [9] + -------------------------------------------------------------------------------- n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- diff --git a/massif/tests/thresholds_10_10.post.exp b/massif/tests/thresholds_10_10.post.exp index ad56e908ad..5c2139ef0e 100644 --- a/massif/tests/thresholds_10_10.post.exp +++ b/massif/tests/thresholds_10_10.post.exp @@ -26,11 +26,12 @@ ms_print arguments: massif.out --threshold=10 | : : ::: : @ | : : ::: : @ | : : ::: : @ - 0 +-----------------------------------------------------------------------@KB + 0 +----------------------------------------------------------------------->KB 0 39.06 Number of snapshots: 10 Detailed snapshots: [9] + -------------------------------------------------------------------------------- n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- diff --git a/massif/tests/thresholds_5_0.post.exp b/massif/tests/thresholds_5_0.post.exp index cb5ee8fa6d..8e8edc6ca1 100644 --- a/massif/tests/thresholds_5_0.post.exp +++ b/massif/tests/thresholds_5_0.post.exp @@ -26,11 +26,12 @@ ms_print arguments: massif.out --threshold=0 | : : ::: : @ | : : ::: : @ | : : ::: : @ - 0 +-----------------------------------------------------------------------@KB + 0 +----------------------------------------------------------------------->KB 0 39.06 Number of snapshots: 10 Detailed snapshots: [9] + -------------------------------------------------------------------------------- n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- diff --git a/massif/tests/thresholds_5_10.post.exp b/massif/tests/thresholds_5_10.post.exp index 272e205841..d67b8f70ba 100644 --- a/massif/tests/thresholds_5_10.post.exp +++ b/massif/tests/thresholds_5_10.post.exp @@ -26,11 +26,12 @@ ms_print arguments: massif.out --threshold=10 | : : ::: : @ | : : ::: : @ | : : ::: : @ - 0 +-----------------------------------------------------------------------@KB + 0 +----------------------------------------------------------------------->KB 0 39.06 Number of snapshots: 10 Detailed snapshots: [9] + -------------------------------------------------------------------------------- n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- diff --git a/massif/tests/zero1.post.exp b/massif/tests/zero1.post.exp index 9798982724..faffb80962 100644 --- a/massif/tests/zero1.post.exp +++ b/massif/tests/zero1.post.exp @@ -26,11 +26,12 @@ ms_print arguments: --threshold=0 massif.out | | | - 0 +@---------------------------------------------------------------------->B + 0 +----------------------------------------------------------------------->B 0 1 Number of snapshots: 21 Detailed snapshots: [9, 19] + -------------------------------------------------------------------------------- n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- diff --git a/massif/tests/zero2.post.exp b/massif/tests/zero2.post.exp index ba2fea8474..75d8e7d031 100644 --- a/massif/tests/zero2.post.exp +++ b/massif/tests/zero2.post.exp @@ -26,11 +26,12 @@ ms_print arguments: massif.out | | | - 0 +@---------------------------------------------------------------------->B + 0 +----------------------------------------------------------------------->B 0 1 Number of snapshots: 21 Detailed snapshots: [9, 19] + -------------------------------------------------------------------------------- n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) --------------------------------------------------------------------------------