PIPS
mem_spy.c File Reference
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "misc-local.h"
+ Include dependency graph for mem_spy.c:

Go to the source code of this file.

Data Structures

struct  _MemSpyStack
 

Macros

#define ABS(x)   ((x>0)?(x):-(x))
 MEM_SPY : Package to track memory usage. More...
 
#define TailleDeMaPile   30
 My own stack (do not rely on any package!) More...
 

Typedefs

typedef struct _MemSpyStack _MemSpyStack
 
typedef struct _MemSpyStackMemSpyStack
 

Functions

void mem_spy_init (int v, double g, measurement_type t, int unit)
 
void mem_spy_reset ()
 
static int current_memory_size ()
 
void mem_spy_begin ()
 
void mem_spy_end (char *s)
 
void mem_spy_info ()
 To print mallinfo, for debugging memory leaks. More...
 

Variables

static MemSpyStack current_size_stack = NULL
 To store the memory size at program section entry. More...
 
static MemSpyStack cumul_size_stack = NULL
 To store the cumulated memory size of inner guarded sections. More...
 
static int MemSpyUsed = 0
 To print only wanted results (and be sure that stacks have been initialized :-) More...
 
static int verbosity = 2
 To control verbosity: from 2, max, to -1, shut up. More...
 
static double granularity = 0.
 To control granularity: threshold in MB for reporting changes in memory use. More...
 
static measurement_type measurement = NET_MEASURE
 measurement chosen More...
 
static int log_of_unit = 0
 log2 of unit chosen: 0 = Byte, 10 = KB, 20 = MB More...
 

Macro Definition Documentation

◆ ABS

#define ABS (   x)    ((x>0)?(x):-(x))

MEM_SPY : Package to track memory usage.

Beatrice Creusillet - August 1995 Usage:

~ mem_spy_init() allocates and initializes all that is needed. ~ mem_spy_reset() frees the allocated memory after using mem_spy. ~ put mem_spy_begin() at the entry of the code section you want to spy, and mem_spy_end("<whatever you want>") at the end. It will print a line on stderr with the following format:

MEM_SPY <whatever you want> begin: *MB end: *MB diff: *MB proper: *MB

each * being a floating number.

~ <begin> is the memory usage at the entry of the code section. ~ <end> is the memory usage at the end of the code section. ~ <diff> is the memory allocation between the two points. ~ <proper> is <diff> minus the memory usage of nested code fragment guarded with mem_spy_begin and mem_spy_end;

You can use mem_spy_begin and mem_spy_end in functions even if mem_spy_init and mem_spy_reset are not used on all paths leading to them. On these paths, no output will be produced (this is what the variable MemSpyUsed is used for).

Notice that MEM_SPY does not rely on any other package, except stdio, string and malloc. Thus, you can use it wherever you want.

TailleDeMaPile = Max number of nested (mem_spy_begin, mem_spy_end). Please change this number accordingly to your needs.

Modifications:

  • verbosity parameter added
  • sbrk(0) replaced by mallinfo() to obtain more precise information
  • new function mem_spy_info() to print mallinfo this is not portable use wait3 sys call or whatever extern int etext;

Definition at line 77 of file mem_spy.c.

◆ TailleDeMaPile

#define TailleDeMaPile   30

My own stack (do not rely on any package!)

Definition at line 80 of file mem_spy.c.

Typedef Documentation

◆ _MemSpyStack

typedef struct _MemSpyStack _MemSpyStack

◆ MemSpyStack

typedef struct _MemSpyStack * MemSpyStack

Function Documentation

◆ current_memory_size()

static int current_memory_size ( )
static

struct mallinfo heap_info;

heap_info = mallinfo();

sbrk(0) - etext

memory_size = heap_info.uordblks-8*heap_info.ordblks;

memory_size = heap_info.uordbytes;

Definition at line 149 of file mem_spy.c.

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 }
static measurement_type measurement
measurement chosen
Definition: mem_spy.c:108
@ 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

References abort, GROSS_MEASURE, measurement, NET_MEASURE, and SBRK_MEASURE.

Referenced by mem_spy_begin(), and mem_spy_end().

+ Here is the caller graph for this function:

◆ mem_spy_begin()

void mem_spy_begin ( )

Do nothing if not between <mem_spy_init> ... <mem_spy_reset>

Do not go beyond stack limits

Push the current memory size

Push 0 on the cumul_size_stack, since there are currently no nested guarded code fragment

Definition at line 175 of file mem_spy.c.

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 }
static MemSpyStack current_size_stack
To store the memory size at program section entry.
Definition: mem_spy.c:89
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
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
#define assert(ex)
Definition: newgen_assert.h:41
int index
Definition: mem_spy.c:83
double elt[TailleDeMaPile]
Definition: mem_spy.c:84

References assert, cumul_size_stack, current_memory_size(), current_size_stack, _MemSpyStack::elt, _MemSpyStack::index, log_of_unit, MemSpyUsed, and TailleDeMaPile.

+ Here is the call graph for this function:

◆ mem_spy_end()

void mem_spy_end ( char *  s)

Do nothing if not between <mem_spy_init> ... <mem_spy_reset>

Too many dynamic calls to mem_spy_end()?

Pop memory size at entry of the code fragment

Pop cumulated memory size of nested guarded code fragments

Calculate consumed and proper memory sizes

if verbosity==-1, nothing is printed

Prettyprint the results

Add the consumed memory size to the previous level cumulated memory size of nested guarded code fragments.

Definition at line 200 of file mem_spy.c.

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 }
static int verbosity
To control verbosity: from 2, max, to -1, shut up.
Definition: mem_spy.c:100
static double granularity
To control granularity: threshold in MB for reporting changes in memory use.
Definition: mem_spy.c:105
#define ABS(x)
MEM_SPY : Package to track memory usage.
Definition: mem_spy.c:77
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...

References abort, ABS, cumul_size_stack, current_memory_size(), current_size_stack, _MemSpyStack::elt, fprintf(), granularity, _MemSpyStack::index, log_of_unit, MemSpyUsed, and verbosity.

+ Here is the call graph for this function:

◆ mem_spy_info()

void mem_spy_info ( )

To print mallinfo, for debugging memory leaks.

struct mallinfo heap_info = mallinfo();

fprintf(stderr, "total space in arena: \t%d", heap_info.arena); fprintf(stderr, "number of ordinary blocks: \t%d", heap_info.ordblks); fprintf(stderr, "number of small blocks: \t%d", heap_info.smblks); fprintf(stderr, "number of holding blocks: \t%d", heap_info.hblks); fprintf(stderr, "space in holding block headers: \t%d", heap_info.hblkhd); fprintf(stderr, "space in small blocks in use: \t%d", heap_info.usmblks); fprintf(stderr, "space in free small blocks: \t%d", heap_info.fsmblks); fprintf(stderr, "space in ordinary blocks in use: \t%d", heap_info.uordblks); fprintf(stderr, "space in free ordinary blocks: \t%d", heap_info.fordblks); fprintf(stderr, "cost of enabling keep option: \t%d", heap_info.keepcost); fprintf(stderr, "max size of small blocks: \t%d", heap_info.mxfast); fprintf(stderr, "number of small blocks in a holding block: \t%d", heap_info.nlblks); fprintf(stderr, "small block rounding factor: \t%d", heap_info.grain); fprintf(stderr, "space (including overhead) allocated in ord. blks: \t%d", heap_info.uordbytes); fprintf(stderr, "number of ordinary blocks allocated: \t%d", heap_info.allocated); fprintf(stderr, "bytes used in maintaining the free tree: \t%d", heap_info.treeoverhead);

Definition at line 276 of file mem_spy.c.

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 }

◆ mem_spy_init()

void mem_spy_init ( int  v,
double  g,
measurement_type  t,
int  unit 
)

Definition at line 113 of file mem_spy.c.

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 }
void * malloc(YYSIZE_T)
struct _MemSpyStack * MemSpyStack
int unit
UNIT.
Definition: newgen_types.h:97

References assert, cumul_size_stack, current_size_stack, granularity, _MemSpyStack::index, log_of_unit, malloc(), measurement, MemSpyUsed, and verbosity.

+ Here is the call graph for this function:

◆ mem_spy_reset()

void mem_spy_reset ( )

Too many dynamic calls to mem_spy_begin()?

Definition at line 129 of file mem_spy.c.

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 }
void free(void *)

References cumul_size_stack, current_size_stack, fprintf(), free(), _MemSpyStack::index, MemSpyUsed, and verbosity.

+ Here is the call graph for this function:

Variable Documentation

◆ cumul_size_stack

MemSpyStack cumul_size_stack = NULL
static

To store the cumulated memory size of inner guarded sections.

Definition at line 92 of file mem_spy.c.

Referenced by mem_spy_begin(), mem_spy_end(), mem_spy_init(), and mem_spy_reset().

◆ current_size_stack

MemSpyStack current_size_stack = NULL
static

To store the memory size at program section entry.

Definition at line 89 of file mem_spy.c.

Referenced by mem_spy_begin(), mem_spy_end(), mem_spy_init(), and mem_spy_reset().

◆ granularity

double granularity = 0.
static

To control granularity: threshold in MB for reporting changes in memory use.

0.004 is about one page.

Definition at line 105 of file mem_spy.c.

Referenced by mem_spy_end(), and mem_spy_init().

◆ log_of_unit

int log_of_unit = 0
static

log2 of unit chosen: 0 = Byte, 10 = KB, 20 = MB

Definition at line 111 of file mem_spy.c.

Referenced by mem_spy_begin(), mem_spy_end(), and mem_spy_init().

◆ measurement

measurement_type measurement = NET_MEASURE
static

measurement chosen

Definition at line 108 of file mem_spy.c.

Referenced by current_memory_size(), and mem_spy_init().

◆ MemSpyUsed

int MemSpyUsed = 0
static

To print only wanted results (and be sure that stacks have been initialized :-)

Definition at line 97 of file mem_spy.c.

Referenced by mem_spy_begin(), mem_spy_end(), mem_spy_init(), and mem_spy_reset().

◆ verbosity

int verbosity = 2
static

To control verbosity: from 2, max, to -1, shut up.

Definition at line 100 of file mem_spy.c.

Referenced by mem_spy_end(), mem_spy_init(), and mem_spy_reset().