source: vis_dev/vis-2.3/share/memoryaccount

Last change on this file was 14, checked in by cecile, 15 years ago

vis2.3

  • Property svn:executable set to *
File size: 8.0 KB
Line 
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.