source: vis_dev/vis-2.3/share/memoryaccount @ 77

Last change on this file since 77 was 14, checked in by cecile, 13 years ago

vis2.3

  • Property svn:executable set to *
File size: 8.0 KB
RevLine 
[14]1#!/usr/local/bin/perl
2#
3# Script to read a file specifying the packages to which every function belongs
4# in VIS and then process the file output of purify and create a table of
5# memory usage per package.
6#
7# Abelardo Pardo <abel@vlsi.colorado.edu>
8#
9# Revision: [$Id: memoryaccount,v 1.8 1997/01/23 03:50:43 hsv Exp $]
10
11require 5.001;
12use Getopt::Long;
13
14$version = "1.8";
15
16# Define option and default variables
17#
18$opt_f = 0;
19$opt_h = 0;
20$opt_p = 0;
21$opt_v = 0;
22$opt_u = 0;
23
24# Read the options
25#
26$optionResult = GetOptions("f=s","h","m=s","p","u=s","v");
27
28# Read the result of the options
29#
30if ($opt_f) {
31    $file = $opt_f;
32}
33else {
34    $file = "purify.log";
35}
36
37# Print the help message if required
38#
39if ($opt_h || !$optionResult) {
40    goto usage;
41}
42
43if ($opt_u) {
44    if ($opt_u eq "k") {
45        $unit = "Kbytes";
46        $factor = 1000.0;
47        $precission = 2;
48    }
49    if ($opt_u eq "m") {
50        $unit = "Mbytes";
51        $factor = 1000000.0;
52        $precission = 2;
53    }
54    if ($opt_u eq "g") {
55        $unit = "Gbytes";
56        $factor = 1000000000.0;
57        $precission = 2;
58    }
59    if ($opt_u eq "b") {
60        $unit = "bytes";
61        $factor = 1.0;
62        $precission = 0;
63    }
64}
65else {
66    $unit = "bytes";
67    $factor = 1.0;
68    $precission = 0;
69}
70
71# Print the version if required
72#
73if ($opt_v) {
74    print <<ENDOFMESSAGE;
75$0 -- Version: $version -- by Abelardo Pardo <abel\@vlsi.colorado.edu>
76ENDOFMESSAGE
77    exit;
78}
79
80# Initial value of certain variables
81#
82$detectedmiu = 0;
83$totalchunks = 0;
84$totalmemory = 0;
85
86# Read in the function map files
87#
88
89if ($#ARGV == -1) {
90    push(@ARGV, "./.fmap");
91}
92
93foreach $filename (@ARGV) {
94    if (open(INPUT, $filename)) {
95        while (<INPUT>) {
96            @fields = split(/\s/,$_);
97            $func2pkg{$fields[2]} = $fields[0];
98            $total{$fields[0]} = 0;
99        }
100        close(INPUT);
101    }
102}
103
104# Open the input file
105#
106open(INPUT, $file) || die "Unable to open file $file\n";
107while (<INPUT>) {
108    chop;
109
110    # Detect the version of purify being executed
111    if (/\s\s\*\sPurify\s([0-9\.]+)\s/) {
112        $purifyVersion = $1;
113        print "Memory Map of $pname at $pdate obtained with Purify $1\n";
114        if ($purifyVersion eq "3.2") {
115            $totalMemoryExp = "^Memory\\sin\\-use:\\s([0-9]+)\\sbytes";
116        }
117        if ($purifyVersion eq "4.0.1") {
118            $totalMemoryExp = "^New\\smemory\\sin\\-use:\\s([0-9]+)\\sbytes";
119        }
120    }
121
122    # Detect the first line telling when this was executed
123    if (/^\*\*\*\*\s\sPurify\sinstrumented\s(.+)\s\((.+)\sat\s(.+)\)/) {
124        $pname = $2;
125        $pdate = $3;
126    }
127
128    # Detecting when the data structure has to be flushed
129    if (/^Purify:\sSearching\sfor\sall\smemory\sin\-use\.\.\.$/) {
130        foreach $name (keys %total) {
131            $total{$name} = 0;
132        }
133        $parsing = 1;
134    }
135
136    if ($parsing) {
137        # Detect the line saying how much memory in use is visible
138        if (/^Memory\sin\-use:\s([0-9]+)\sbytes\s+\(([0-9\.]+)%\s.+\)/) {
139            $memInUse = $2;
140        }
141       
142        # If we are inside a MIU statement
143        if ($detectedmiu == 1) {
144           
145            # Detect end of MIU statement
146            if ($_ eq "") {
147                $detectedmiu = 0;
148                if ($notallocatedyet == 1) {
149                    $total{"unclaimed"} += $portioninuse;
150                }
151            }
152            else {
153               
154                # Obtain the function name of the allocation
155                if ($notallocatedyet == 1) {
156                    if (/\s+([a-zA-Z0-9_]+)\s+\[(.+)\]/) {
157                        $function = $1;
158                        if (defined($func2pkg{$function})) {
159                            $pkg = $func2pkg{$function};
160                            $total{$pkg} += $portioninuse;
161                            $notallocatedyet = 0;
162                        }
163                    }
164                }
165            }
166        }
167       
168        if (/^MIU:\s([0-9]+)\sbytes/) {
169            $detectedmiu = 1;
170            $portioninuse = $1;
171            $notallocatedyet = 1;
172        }
173       
174        if (/^\s\s\s\s\sTotal\sAllocated\s+([0-9]+)\s+([0-9]+)/) {
175            $totalchunks = $1;
176            $totalmemory = $2;
177            $parsing = 0;
178        }
179    }
180}
181
182close(INPUT);
183
184if ($memInUse ne "100") {
185    print "Warning: The program is using $memInUse% of its allocated memory\n";
186}
187print "Profile of the memory currently in use:\n";
188foreach $name (sort keys %total) {
189    if ($opt_p || $total{$name} != 0) {
190        $tmemoryunits = $total{$name}/$factor;
191        $percentage = 100.0*$total{$name}/$totalmemory;
192        printf "%9s :  %12.${precission}f %s %5.2f %%\n", 
193               $name, $tmemoryunits, $unit, $percentage;
194    }
195}
196print "-------------------------------------------------------------------------------\n";
197
198if ($totalchunks == 0) {
199    print "No information found in file $file\n";
200    exit;
201}
202
203$memoryunits = $totalmemory/$factor;
204$memoryperchunk = $totalmemory/$totalchunks;
205printf "Total Memory Allocated = %12.${precission}f %s\n", $memoryunits, $unit;
206print "Memory allocated in $totalchunks portions. ";
207printf "Average %12.2f bytes per portion\n", $memoryperchunk;
208
209exit;
210
211usage:
212    print <<ENDOFMESSAGE;
213
214$0 - Program to analyze and collect statistics about the memory usage of VIS.
215    This is how the filter works. It reads a file mapping function names to
216    package names. The filename to read may be provided in the command
217    line. This map may be created with the script "createfunctionmap". The
218    application first reads in that function map. If a function is mapped in
219    more than one file, the last one read in the one that prevails (for that
220    reason it is recommended to read in first the global map and then the map
221    in the user area). After that, it opens the file "purify.log" (this value
222    may be overwritten with the "-f" option). It parses this file to detect the
223    beginning and end of the purify dump of the memory in use. Among other
224    things, the parsing analyzes every MIU (Memory in use) statement. The MIU
225    statement gives the call stack whenever a memory allocation of a portion
226    that is still in use is performed. The script parses this call stack
227    searching for function names. When a function name that is present in the
228    map previously read is found, that memory is added to a counter for the
229    package to which that function belongs. Since purify prints a finite number
230    of functions in this call stack, it might happen that none of the function
231    names in that stack is in the map. In that case, the memory allocated is
232    accounted to the "unclaimed" category.  If while using this script, the
233    unclaimed category represents a significant portion of the memory in use,
234    there are two things that can be done: Either the length of the call stack
235    is increased by using the "-chain-length" option in purify whose default is
236    6, or more function names are included in the map file, such that the
237    "unclaimed memory" situation does not occur that often.  When the script is
238    done parsing the purify file, it prints a summary of the memory allocated
239    to each and every package present in its map. Purify makes a distinction
240    between the memory in use and the allocated memory. The former is the
241    memory that is still accessible to the program. The latter is the total
242    memory allocated to the program. If the memory being used by the program is
243    not the total memory allocated by the program, the script issues a
244    warning. This situation means that there is a portion of the memory that
245    cannot be accessed and therefore leaked. Please refer to the purify user's
246    guide Chapter 14, "Purify API" for more information about the type of
247    information provided by purify.
248
249Usage:
250  $0 [-f <filename>] [-h] [-p] [-v] [-u <units>] filenames
251
252Options:
253  -f <filename>     File to read the dump from. The default is "purify.log"
254  -h                Print this message
255  -p                Print also the packages that do not use any memory.
256  -v                Print the version
257  -u <units>        Units to print the memory usage in. It may be "b" for bytes
258                    "k" for kilobytes, "m" for megabytes and "g" for gigabytes.
259                    The default is bytes.
260  filenames         Files containing the function map to be read. Default is
261                    ./.fmap
262
263Bugs:
264  This script has been tested for purify versions 3.2 and 4.0.1. Since the
265  parsing is sensitive to the messages written in the dump file, a new version
266  of purify might have different messages that are not matched in the
267  script. If this situation arises, chances are the results are completely
268  bogus.
269
270Author: Abelardo Pardo <abel\@vlsi.colorado.edu>
271
272
273ENDOFMESSAGE
274    exit;
Note: See TracBrowser for help on using the repository browser.