PIPS
mem_spy.c
Go to the documentation of this file.
1 /*
2 
3  $Id: mem_spy.c 23065 2016-03-02 09:05:50Z coelho $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of PIPS.
8 
9  PIPS is free software: you can redistribute it and/or modify it
10  under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  any later version.
13 
14  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
15  WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  FITNESS FOR A PARTICULAR PURPOSE.
17 
18  See the GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 #ifdef HAVE_CONFIG_H
25  #include "pips_config.h"
26 #endif
27 /* MEM_SPY : Package to track memory usage.
28  * Beatrice Creusillet - August 1995
29  */
30 /* Usage:
31  *
32  * ~ mem_spy_init() allocates and initializes all that is needed.
33  * ~ mem_spy_reset() frees the allocated memory after using mem_spy.
34  * ~ put mem_spy_begin() at the entry of the code section you want to
35  * spy, and mem_spy_end("<whatever you want>") at the end. It will
36  * print a line on stderr with the following format:
37  *
38  * MEM_SPY <whatever you want> begin: *MB end: *MB diff: *MB proper: *MB
39  *
40  * each * being a floating number.
41  *
42  * ~ <begin> is the memory usage at the entry of the code section.
43  * ~ <end> is the memory usage at the end of the code section.
44  * ~ <diff> is the memory allocation between the two points.
45  * ~ <proper> is <diff> minus the memory usage of nested code fragment
46  * guarded with mem_spy_begin and mem_spy_end;
47  *
48  * You can use mem_spy_begin and mem_spy_end in functions even if mem_spy_init
49  * and mem_spy_reset are not used on all paths leading to them.
50  * On these paths, no output will be produced (this is what the variable
51  * MemSpyUsed is used for).
52  *
53  * Notice that MEM_SPY does not rely on any other package, except stdio,
54  * string and malloc. Thus, you can use it wherever you want.
55  *
56  * TailleDeMaPile = Max number of nested (mem_spy_begin, mem_spy_end).
57  * Please change this number accordingly to your needs.
58  *
59  * Modifications:
60  * - verbosity parameter added
61  * - sbrk(0) replaced by mallinfo() to obtain more precise information
62  * - new function mem_spy_info() to print mallinfo
63  */
64 
65 #include <stdlib.h>
66 #include <stdio.h>
67 #include <string.h>
68 #include <stdlib.h>
69 #include <assert.h>
70 
71 /* this is **not** portable */
72 /* use wait3 sys call or whatever */
73 /* extern int etext; */
74 
75 #include "misc-local.h"
76 
77 #define ABS(x) ((x>0)?(x):-(x))
78 
79 /* My own stack (do not rely on any package!) */
80 #define TailleDeMaPile 30
81 typedef struct _MemSpyStack
82 {
83  int index;
86 
87 
88 /* To store the memory size at program section entry */
90 
91 /* To store the cumulated memory size of inner guarded sections */
93 
94 /* To print only wanted results
95  * (and be sure that stacks have been initialized :-)
96 */
97 static int MemSpyUsed = 0;
98 
99 /* To control verbosity: from 2, max, to -1, shut up */
100 static int verbosity = 2;
101 
102 /* To control granularity: threshold in MB for reporting changes in memory
103  * use. 0.004 is about one page.
104  */
105 static double granularity = 0.;
106 
107 /* measurement chosen */
109 
110 /* log2 of unit chosen: 0 = Byte, 10 = KB, 20 = MB */
111 static int log_of_unit = 0;
112 
113 void mem_spy_init(int v, double g, measurement_type t, int unit)
114 {
115  assert(-1<=v && v<=2);
116  assert(0<=unit && unit<=20);
117  verbosity = v;
118  granularity = g;
119  measurement = t;
120  log_of_unit = unit;
121 
122  MemSpyUsed = 1;
126  cumul_size_stack->index = -1;
127 }
128 
130 {
131  /* Too many dynamic calls to mem_spy_begin()? */
132  if(current_size_stack->index!=-1) {
133  fprintf(stderr,
134  "Too many calls to mem_spy_begin(), non-empty stack reset\n");
135  }
136 
137  if (MemSpyUsed == 1)
138  {
139  MemSpyUsed = 0;
140  if (current_size_stack != NULL)
142  if (cumul_size_stack != NULL)
144  }
145  verbosity = 2;
146 }
147 
148 static int
150 {
151  /* struct mallinfo heap_info; */
152  int memory_size;
153 
154  /* heap_info = mallinfo(); */
155 
156  switch(measurement) {
157  case SBRK_MEASURE:
158  memory_size = /* sbrk(0) - etext*/ -1;
159  break;
160  case NET_MEASURE:
161  /* memory_size = heap_info.uordblks-8*heap_info.ordblks; */
162  memory_size = -1;
163  break;
164  case GROSS_MEASURE:
165  /* memory_size = heap_info.uordbytes; */
166  memory_size = -1;
167  break;
168  default:
169  abort();
170  }
171 
172  return memory_size;
173 }
174 
176 {
177 
178  /* Do nothing if not between <mem_spy_init> ... <mem_spy_reset> */
179  if (MemSpyUsed == 1)
180  {
181  int memory_size = current_memory_size();
182 
183  /* Do not go beyond stack limits */
185 
186  /* Push the current memory size */
188 
190  (double) (memory_size/(double)(1 << log_of_unit));
191 
192  /* Push 0 on the cumul_size_stack, since there are currently
193  * no nested guarded code fragment
194  */
195  cumul_size_stack->index += 1;
196  cumul_size_stack->elt[cumul_size_stack->index] = (double) 0;
197  }
198 }
199 
200 void mem_spy_end(s)
201 char * s;
202 {
203  double current_begin, current_end, cumul, diff, proper;
204  int i;
205 
206  /* Do nothing if not between <mem_spy_init> ... <mem_spy_reset> */
207  if (MemSpyUsed == 1)
208  {
209  int memory_size = current_memory_size();
210  char * format;
211 
212  /* Too many dynamic calls to mem_spy_end()? */
213  if(current_size_stack->index<0) {
214  fprintf(stderr,
215  "Too many calls to mem_spy_end(), stack underflow\n");
216  abort();
217  }
218 
219  switch(log_of_unit) {
220  case 0: format =
221  "MEM_SPY "
222  "[%s] begin: %10.0f B end: %10.0f B diff: %10.0f B "
223  "proper: %10.0f B\n";
224  break;
225  case 10: format =
226  "MEM_SPY "
227  "[%s] begin: %10.3f KB end: %10.3f KB diff: %10.3f KB "
228  "proper: %10.3f KB\n";
229  break;
230  case 20: format =
231  "MEM_SPY "
232  "[%s] begin: %10.6f MB end: %10.6f MB diff: %10.6f MB "
233  "proper: %10.6f MB\n";
234  break;
235  default: format =
236  "MEM_SPY (unknown unit %d) "
237  "[%s] begin: %10.6f (?) end: %10.6f (?) diff: %10.6f (?) "
238  "proper: %10.6f (?)\n";
239  break;
240  }
241 
242  /* Pop memory size at entry of the code fragment */
243  current_end = memory_size/(double)(1 << log_of_unit);
244  current_begin = current_size_stack->elt[current_size_stack->index];
246 
247  /* Pop cumulated memory size of nested guarded code fragments */
249  cumul_size_stack->index -= 1;
250 
251  /* Calculate consumed and proper memory sizes */
252  diff = current_end - current_begin;
253  proper = diff - cumul;
254 
255  /* if verbosity==-1, nothing is printed */
256  if(verbosity==2 ||
257  (verbosity==1 && ABS(diff) >= granularity) ||
258  (verbosity==0 && ABS(proper) >= granularity)) {
259  /* Prettyprint the results */
260  for (i=0; i<=current_size_stack->index; i++)
261  fprintf(stderr, " ");
262 
263  fprintf(stderr, format,
264  s, current_begin, current_end, diff, proper);
265  }
266 
267  /* Add the consumed memory size to the previous level cumulated
268  * memory size of nested guarded code fragments.
269  */
270  if (cumul_size_stack->index != -1)
272  }
273 }
274 
275 /* To print mallinfo, for debugging memory leaks*/
277 {
278  /*
279  struct mallinfo heap_info = mallinfo();
280 
281  fprintf(stderr, "total space in arena: \t%d", heap_info.arena);
282  fprintf(stderr, "number of ordinary blocks: \t%d", heap_info.ordblks);
283  fprintf(stderr, "number of small blocks: \t%d", heap_info.smblks);
284  fprintf(stderr, "number of holding blocks: \t%d", heap_info.hblks);
285  fprintf(stderr, "space in holding block headers: \t%d", heap_info.hblkhd);
286  fprintf(stderr, "space in small blocks in use: \t%d", heap_info.usmblks);
287  fprintf(stderr, "space in free small blocks: \t%d", heap_info.fsmblks);
288  fprintf(stderr, "space in ordinary blocks in use: \t%d", heap_info.uordblks);
289  fprintf(stderr, "space in free ordinary blocks: \t%d", heap_info.fordblks);
290  fprintf(stderr, "cost of enabling keep option: \t%d", heap_info.keepcost);
291  fprintf(stderr, "max size of small blocks: \t%d", heap_info.mxfast);
292  fprintf(stderr, "number of small blocks in a holding block: \t%d", heap_info.nlblks);
293  fprintf(stderr, "small block rounding factor: \t%d", heap_info.grain);
294  fprintf(stderr, "space (including overhead) allocated in ord. blks: \t%d", heap_info.uordbytes);
295  fprintf(stderr, "number of ordinary blocks allocated: \t%d", heap_info.allocated);
296  fprintf(stderr, "bytes used in maintaining the free tree: \t%d", heap_info.treeoverhead);
297  */
298 }
void * malloc(YYSIZE_T)
void free(void *)
static MemSpyStack current_size_stack
To store the memory size at program section entry.
Definition: mem_spy.c:89
static int verbosity
To control verbosity: from 2, max, to -1, shut up.
Definition: mem_spy.c:100
void mem_spy_reset()
Definition: mem_spy.c:129
void mem_spy_info()
To print mallinfo, for debugging memory leaks.
Definition: mem_spy.c:276
void mem_spy_end(char *s)
Definition: mem_spy.c:200
struct _MemSpyStack * MemSpyStack
static double granularity
To control granularity: threshold in MB for reporting changes in memory use.
Definition: mem_spy.c:105
static MemSpyStack cumul_size_stack
To store the cumulated memory size of inner guarded sections.
Definition: mem_spy.c:92
#define TailleDeMaPile
My own stack (do not rely on any package!)
Definition: mem_spy.c:80
struct _MemSpyStack _MemSpyStack
static measurement_type measurement
measurement chosen
Definition: mem_spy.c:108
#define ABS(x)
MEM_SPY : Package to track memory usage.
Definition: mem_spy.c:77
void mem_spy_begin()
Definition: mem_spy.c:175
static int log_of_unit
log2 of unit chosen: 0 = Byte, 10 = KB, 20 = MB
Definition: mem_spy.c:111
static int MemSpyUsed
To print only wanted results (and be sure that stacks have been initialized :-)
Definition: mem_spy.c:97
static int current_memory_size()
Definition: mem_spy.c:149
void mem_spy_init(int v, double g, measurement_type t, int unit)
Definition: mem_spy.c:113
measurement_type
Measurement type for mem_spy.c.
Definition: misc-local.h:57
@ SBRK_MEASURE
Definition: misc-local.h:57
@ GROSS_MEASURE
Definition: misc-local.h:57
@ NET_MEASURE
Definition: misc-local.h:57
#define abort()
Definition: misc-local.h:53
#define assert(ex)
Definition: newgen_assert.h:41
int unit
UNIT.
Definition: newgen_types.h:97
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
int index
Definition: mem_spy.c:83
double elt[TailleDeMaPile]
Definition: mem_spy.c:84