xref: /petsc/src/sys/memory/mtr.c (revision 97c4aaa0041b17e0788ef5380763993e79c96a23)
1 #define PETSC_DLL
2 /*
3      Interface to malloc() and free(). This code allows for
4   logging of memory usage and some error checking
5 */
6 #include "petscsys.h"           /*I "petscsys.h" I*/
7 #if defined(PETSC_HAVE_STDLIB_H)
8 #include <stdlib.h>
9 #endif
10 #if defined(PETSC_HAVE_MALLOC_H)
11 #include <malloc.h>
12 #endif
13 
14 
15 /*
16      These are defined in mal.c and ensure that malloced space is PetscScalar aligned
17 */
18 EXTERN PetscErrorCode PETSCSYS_DLLEXPORT PetscMallocAlign(size_t,int,const char[],const char[],const char[],void**);
19 EXTERN PetscErrorCode PETSCSYS_DLLEXPORT PetscFreeAlign(void*,int,const char[],const char[],const char[]);
20 EXTERN PetscErrorCode PETSCSYS_DLLEXPORT PetscTrMallocDefault(size_t,int,const char[],const char[],const char[],void**);
21 EXTERN PetscErrorCode PETSCSYS_DLLEXPORT PetscTrFreeDefault(void*,int,const char[],const char[],const char[]);
22 
23 
24 #define CLASSID_VALUE   ((PetscClassId) 0xf0e0d0c9)
25 #define ALREADY_FREED  ((PetscClassId) 0x0f0e0d9c)
26 
27 typedef struct _trSPACE {
28     size_t          size;
29     int             id;
30     int             lineno;
31     const char      *filename;
32     const char      *functionname;
33     const char      *dirname;
34     PetscClassId    classid;
35 #if defined(PETSC_USE_DEBUG) && !defined(PETSC_USE_PTHREAD)
36     PetscStack      stack;
37 #endif
38     struct _trSPACE *next,*prev;
39 } TRSPACE;
40 
41 /* HEADER_BYTES is the number of bytes in a PetscMalloc() header.
42    It is sizeof(TRSPACE) padded to be a multiple of PETSC_MEMALIGN.
43 */
44 
45 #define HEADER_BYTES      (sizeof(TRSPACE)+(PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1)
46 
47 
48 /* This union is used to insure that the block passed to the user retains
49    a minimum alignment of PETSC_MEMALIGN.
50 */
51 typedef union {
52     TRSPACE sp;
53     char    v[HEADER_BYTES];
54 } TrSPACE;
55 
56 
57 static size_t     TRallocated  = 0;
58 static int        TRfrags      = 0;
59 static TRSPACE    *TRhead      = 0;
60 static int        TRid         = 0;
61 static PetscBool  TRdebugLevel = PETSC_FALSE;
62 static size_t     TRMaxMem     = 0;
63 /*
64       Arrays to log information on all Mallocs
65 */
66 static int        PetscLogMallocMax = 10000,PetscLogMalloc = -1;
67 static size_t     *PetscLogMallocLength;
68 static const char **PetscLogMallocDirectory,**PetscLogMallocFile,**PetscLogMallocFunction;
69 
70 #undef __FUNCT__
71 #define __FUNCT__ "PetscSetUseTrMalloc_Private"
72 PetscErrorCode PetscSetUseTrMalloc_Private(void)
73 {
74 #if !defined(PETSC_USE_PTHREAD)
75   PetscErrorCode ierr;
76 #endif
77 
78   PetscFunctionBegin;
79 #if defined(PETSC_USE_PTHREAD)
80   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot use PETSc's debug malloc when using pthreads");
81 #else
82   ierr              = PetscMallocSet(PetscTrMallocDefault,PetscTrFreeDefault);CHKERRQ(ierr);
83   TRallocated       = 0;
84   TRfrags           = 0;
85   TRhead            = 0;
86   TRid              = 0;
87   TRdebugLevel      = PETSC_FALSE;
88   TRMaxMem          = 0;
89   PetscLogMallocMax = 10000;
90   PetscLogMalloc    = -1;
91   PetscFunctionReturn(0);
92 #endif
93 }
94 
95 #undef __FUNCT__
96 #define __FUNCT__ "PetscMallocValidate"
97 /*@C
98    PetscMallocValidate - Test the memory for corruption.  This can be used to
99    check for memory overwrites.
100 
101    Input Parameter:
102 +  line - line number where call originated.
103 .  function - name of function calling
104 .  file - file where function is
105 -  dir - directory where function is
106 
107    Return value:
108    The number of errors detected.
109 
110    Output Effect:
111    Error messages are written to stdout.
112 
113    Level: advanced
114 
115    Notes:
116     You should generally use CHKMEMQ as a short cut for calling this
117     routine.
118 
119     The line, function, file and dir are given by the C preprocessor as
120     __LINE__, __FUNCT__, __FILE__, and __DIR__
121 
122     The Fortran calling sequence is simply PetscMallocValidate(ierr)
123 
124    No output is generated if there are no problems detected.
125 
126 .seealso: CHKMEMQ
127 
128 @*/
129 PetscErrorCode PETSCSYS_DLLEXPORT PetscMallocValidate(int line,const char function[],const char file[],const char dir[])
130 {
131   TRSPACE     *head,*lasthead;
132   char        *a;
133   PetscClassId *nend;
134 
135   PetscFunctionBegin;
136   head = TRhead; lasthead = NULL;
137   while (head) {
138     if (head->classid != CLASSID_VALUE) {
139       (*PetscErrorPrintf)("PetscMallocValidate: error detected at  %s() line %d in %s%s\n",function,line,dir,file);
140       (*PetscErrorPrintf)("Memory at address %p is corrupted\n",head);
141       (*PetscErrorPrintf)("Probably write past beginning or end of array\n");
142       if (lasthead)
143 	(*PetscErrorPrintf)("Last intact block allocated in %s() line %d in %s%s\n",lasthead->functionname,lasthead->lineno,lasthead->dirname,lasthead->filename);
144       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," ");
145     }
146     a    = (char *)(((TrSPACE*)head) + 1);
147     nend = (PetscClassId *)(a + head->size);
148     if (*nend != CLASSID_VALUE) {
149       (*PetscErrorPrintf)("PetscMallocValidate: error detected at %s() line %d in %s%s\n",function,line,dir,file);
150       if (*nend == ALREADY_FREED) {
151         (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n",head->id,(PetscLogDouble)head->size,a);
152         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," ");
153       } else {
154         (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
155         (*PetscErrorPrintf)("Memory originally allocated in %s() line %d in %s%s\n",head->functionname,head->lineno,head->dirname,head->filename);
156         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," ");
157       }
158     }
159     lasthead = head;
160     head = head->next;
161   }
162   PetscFunctionReturn(0);
163 }
164 
165 #undef __FUNCT__
166 #define __FUNCT__ "PetscTrMallocDefault"
167 /*
168     PetscTrMallocDefault - Malloc with tracing.
169 
170     Input Parameters:
171 +   a   - number of bytes to allocate
172 .   lineno - line number where used.  Use __LINE__ for this
173 .   function - function calling routine. Use __FUNCT__ for this
174 .   filename  - file name where used.  Use __FILE__ for this
175 -   dir - directory where file is. Use __SDIR__ for this
176 
177     Returns:
178     double aligned pointer to requested storage, or null if not
179     available.
180  */
181 PetscErrorCode PETSCSYS_DLLEXPORT PetscTrMallocDefault(size_t a,int lineno,const char function[],const char filename[],const char dir[],void**result)
182 {
183   TRSPACE        *head;
184   char           *inew;
185   size_t         nsize;
186   PetscErrorCode ierr;
187 
188   PetscFunctionBegin;
189   if (!a) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to malloc zero size array");
190 
191   if (TRdebugLevel) {
192     ierr = PetscMallocValidate(lineno,function,filename,dir); if (ierr) PetscFunctionReturn(ierr);
193   }
194 
195   nsize = (a + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1);
196   ierr = PetscMallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),lineno,function,filename,dir,(void**)&inew);CHKERRQ(ierr);
197 
198   head   = (TRSPACE *)inew;
199   inew  += sizeof(TrSPACE);
200 
201   if (TRhead) TRhead->prev = head;
202   head->next     = TRhead;
203   TRhead         = head;
204   head->prev     = 0;
205   head->size     = nsize;
206   head->id       = TRid;
207   head->lineno   = lineno;
208 
209   head->filename     = filename;
210   head->functionname = function;
211   head->dirname      = dir;
212   head->classid       = CLASSID_VALUE;
213   *(PetscClassId *)(inew + nsize) = CLASSID_VALUE;
214 
215   TRallocated += nsize;
216   if (TRallocated > TRMaxMem) {
217     TRMaxMem   = TRallocated;
218   }
219   TRfrags++;
220 
221 #if defined(PETSC_USE_DEBUG) && !defined(PETSC_USE_PTHREAD)
222   ierr = PetscStackCopy(petscstack,&head->stack);CHKERRQ(ierr);
223 #endif
224 
225   /*
226          Allow logging of all mallocs made
227   */
228   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax) {
229     if (!PetscLogMalloc) {
230       PetscLogMallocLength    = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t));
231       if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
232       PetscLogMallocDirectory = (const char**)malloc(PetscLogMallocMax*sizeof(char**));
233       if (!PetscLogMallocDirectory) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
234       PetscLogMallocFile      = (const char**)malloc(PetscLogMallocMax*sizeof(char**));
235       if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
236       PetscLogMallocFunction  = (const char**)malloc(PetscLogMallocMax*sizeof(char**));
237       if (!PetscLogMallocFunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
238     }
239     PetscLogMallocLength[PetscLogMalloc]      = nsize;
240     PetscLogMallocDirectory[PetscLogMalloc]   = dir;
241     PetscLogMallocFile[PetscLogMalloc]        = filename;
242     PetscLogMallocFunction[PetscLogMalloc++]  = function;
243   }
244   *result = (void*)inew;
245   PetscFunctionReturn(0);
246 }
247 
248 
249 #undef __FUNCT__
250 #define __FUNCT__ "PetscTrFreeDefault"
251 /*
252    PetscTrFreeDefault - Free with tracing.
253 
254    Input Parameters:
255 .   a    - pointer to a block allocated with PetscTrMalloc
256 .   lineno - line number where used.  Use __LINE__ for this
257 .   function - function calling routine. Use __FUNCT__ for this
258 .   file  - file name where used.  Use __FILE__ for this
259 .   dir - directory where file is. Use __SDIR__ for this
260  */
261 PetscErrorCode PETSCSYS_DLLEXPORT PetscTrFreeDefault(void *aa,int line,const char function[],const char file[],const char dir[])
262 {
263   char           *a = (char*)aa;
264   TRSPACE        *head;
265   char           *ahead;
266   PetscErrorCode ierr;
267   PetscClassId   *nend;
268 
269   PetscFunctionBegin;
270   /* Do not try to handle empty blocks */
271   if (!a) {
272     (*PetscErrorPrintf)("PetscTrFreeDefault called from %s() line %d in %s%s\n",function,line,dir,file);
273     SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to free null block: Free called from %s() line %d in %s%s\n",function,line,dir,file);
274   }
275 
276   if (TRdebugLevel) {
277     ierr = PetscMallocValidate(line,function,file,dir);CHKERRQ(ierr);
278   }
279 
280   ahead = a;
281   a     = a - sizeof(TrSPACE);
282   head  = (TRSPACE *)a;
283 
284   if (head->classid != CLASSID_VALUE) {
285     (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s%s\n",function,line,dir,file);
286     (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a);
287     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory");
288   }
289   nend = (PetscClassId *)(ahead + head->size);
290   if (*nend != CLASSID_VALUE) {
291     if (*nend == ALREADY_FREED) {
292       (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s%s\n",function,line,dir,file);
293       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE));
294       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
295 	(*PetscErrorPrintf)("Block freed in %s() line %d in %s%s\n",head->functionname,head->lineno,head->dirname,head->filename);
296       } else {
297         (*PetscErrorPrintf)("Block allocated in %s() line %d in %s%s\n",head->functionname,-head->lineno,head->dirname,head->filename);
298       }
299       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed");
300     } else {
301       /* Damaged tail */
302       (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s%s\n",function,line,dir,file);
303       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
304       (*PetscErrorPrintf)("Block allocated in %s() line %d in %s%s\n",head->functionname,head->lineno,head->dirname,head->filename);
305       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory");
306     }
307   }
308   /* Mark the location freed */
309   *nend        = ALREADY_FREED;
310   /* Save location where freed.  If we suspect the line number, mark as  allocated location */
311   if (line > 0 && line < 50000) {
312     head->lineno       = line;
313     head->filename     = file;
314     head->functionname = function;
315     head->dirname      = dir;
316   } else {
317     head->lineno = - head->lineno;
318   }
319   /* zero out memory - helps to find some reuse of already freed memory */
320   ierr = PetscMemzero(aa,head->size);CHKERRQ(ierr);
321 
322   TRallocated -= head->size;
323   TRfrags     --;
324   if (head->prev) head->prev->next = head->next;
325   else TRhead = head->next;
326 
327   if (head->next) head->next->prev = head->prev;
328   ierr = PetscFreeAlign(a,line,function,file,dir);CHKERRQ(ierr);
329   PetscFunctionReturn(0);
330 }
331 
332 
333 #undef __FUNCT__
334 #define __FUNCT__ "PetscMemoryShowUsage"
335 /*@C
336     PetscMemoryShowUsage - Shows the amount of memory currently being used
337         in a communicator.
338 
339     Collective on PetscViewer
340 
341     Input Parameter:
342 +    viewer - the viewer that defines the communicator
343 -    message - string printed before values
344 
345     Level: intermediate
346 
347     Concepts: memory usage
348 
349 .seealso: PetscMallocDump(), PetscMemoryGetCurrentUsage()
350  @*/
351 PetscErrorCode PETSCSYS_DLLEXPORT PetscMemoryShowUsage(PetscViewer viewer,const char message[])
352 {
353   PetscLogDouble allocated,maximum,resident,residentmax;
354   PetscErrorCode ierr;
355   PetscMPIInt    rank;
356   MPI_Comm       comm;
357 
358   PetscFunctionBegin;
359   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
360   ierr = PetscMallocGetCurrentUsage(&allocated);CHKERRQ(ierr);
361   ierr = PetscMallocGetMaximumUsage(&maximum);CHKERRQ(ierr);
362   ierr = PetscMemoryGetCurrentUsage(&resident);CHKERRQ(ierr);
363   ierr = PetscMemoryGetMaximumUsage(&residentmax);CHKERRQ(ierr);
364   if (residentmax > 0) residentmax = PetscMax(resident,residentmax);
365   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
366   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
367   ierr = PetscViewerASCIIPrintf(viewer,message);CHKERRQ(ierr);
368   if (resident && residentmax && allocated) {
369     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d]Current space PetscMalloc()ed %g, max space PetscMalloced() %g\n[%d]Current process memory %g max process memory %g\n",rank,allocated,maximum,rank,resident,residentmax);CHKERRQ(ierr);
370   } else if (resident && residentmax) {
371     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d]Run with -malloc to get statistics on PetscMalloc() calls\n[%d]Current process memory %g max process memory %g\n",rank,rank,resident,residentmax);CHKERRQ(ierr);
372   } else if (resident && allocated) {
373     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d]Current space PetscMalloc()ed %g, max space PetscMalloced() %g\n[%d]Current process memory %g, run with -memory_info to get max memory usage\n",rank,allocated,maximum,rank,resident);CHKERRQ(ierr);
374   } else if (allocated) {
375     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d]Current space PetscMalloc()ed %g, max space PetscMalloced() %g\n[%d]OS cannot compute process memory\n",rank,allocated,maximum,rank);CHKERRQ(ierr);
376   } else {
377     ierr = PetscViewerASCIIPrintf(viewer,"Run with -malloc to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n");CHKERRQ(ierr);
378   }
379   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
380   PetscFunctionReturn(0);
381 }
382 
383 #undef __FUNCT__
384 #define __FUNCT__ "PetscMallocGetCurrentUsage"
385 /*@C
386     PetscMallocGetCurrentUsage - gets the current amount of memory used that was PetscMalloc()ed
387 
388     Not Collective
389 
390     Output Parameters:
391 .   space - number of bytes currently allocated
392 
393     Level: intermediate
394 
395     Concepts: memory usage
396 
397 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
398           PetscMemoryGetMaximumUsage()
399  @*/
400 PetscErrorCode PETSCSYS_DLLEXPORT PetscMallocGetCurrentUsage(PetscLogDouble *space)
401 {
402   PetscFunctionBegin;
403   *space = (PetscLogDouble) TRallocated;
404   PetscFunctionReturn(0);
405 }
406 
407 #undef __FUNCT__
408 #define __FUNCT__ "PetscMallocGetMaximumUsage"
409 /*@C
410     PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was PetscMalloc()ed at any time
411         during this run.
412 
413     Not Collective
414 
415     Output Parameters:
416 .   space - maximum number of bytes ever allocated at one time
417 
418     Level: intermediate
419 
420     Concepts: memory usage
421 
422 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
423           PetscMemoryGetCurrentUsage()
424  @*/
425 PetscErrorCode PETSCSYS_DLLEXPORT PetscMallocGetMaximumUsage(PetscLogDouble *space)
426 {
427   PetscFunctionBegin;
428   *space = (PetscLogDouble) TRMaxMem;
429   PetscFunctionReturn(0);
430 }
431 
432 #undef __FUNCT__
433 #define __FUNCT__ "PetscMallocDump"
434 /*@C
435    PetscMallocDump - Dumps the allocated memory blocks to a file. The information
436    printed is: size of space (in bytes), address of space, id of space,
437    file in which space was allocated, and line number at which it was
438    allocated.
439 
440    Collective on PETSC_COMM_WORLD
441 
442    Input Parameter:
443 .  fp  - file pointer.  If fp is NULL, stdout is assumed.
444 
445    Options Database Key:
446 .  -malloc_dump - Dumps unfreed memory during call to PetscFinalize()
447 
448    Level: intermediate
449 
450    Fortran Note:
451    The calling sequence in Fortran is PetscMallocDump(integer ierr)
452    The fp defaults to stdout.
453 
454    Notes: uses MPI_COMM_WORLD, because this may be called in PetscFinalize() after PETSC_COMM_WORLD
455           has been freed.
456 
457    Concepts: memory usage
458    Concepts: memory bleeding
459    Concepts: bleeding memory
460 
461 .seealso:  PetscMallocGetCurrentUsage(), PetscMallocDumpLog()
462 @*/
463 PetscErrorCode PETSCSYS_DLLEXPORT PetscMallocDump(FILE *fp)
464 {
465   TRSPACE        *head;
466   PetscErrorCode ierr;
467   PetscMPIInt    rank;
468 
469   PetscFunctionBegin;
470   ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr);
471   if (!fp) fp = PETSC_STDOUT;
472   if (TRallocated > 0) {
473     fprintf(fp,"[%d]Total space allocated %.0f bytes\n",rank,(PetscLogDouble)TRallocated);
474   }
475   head = TRhead;
476   while (head) {
477     fprintf(fp,"[%2d]%.0f bytes %s() line %d in %s%s\n",rank,(PetscLogDouble)head->size,head->functionname,head->lineno,head->dirname,head->filename);
478 #if defined(PETSC_USE_DEBUG) && !defined(PETSC_USE_PTHREAD)
479     ierr = PetscStackPrint(&head->stack,fp);CHKERRQ(ierr);
480 #endif
481     head = head->next;
482   }
483   PetscFunctionReturn(0);
484 }
485 
486 /* ---------------------------------------------------------------------------- */
487 
488 #undef __FUNCT__
489 #define __FUNCT__ "PetscMallocSetDumpLog"
490 /*@C
491     PetscMallocSetDumpLog - Activates logging of all calls to PetscMalloc().
492 
493     Not Collective
494 
495     Options Database Key:
496 .  -malloc_log - Activates PetscMallocDumpLog()
497 
498     Level: advanced
499 
500 .seealso: PetscMallocDump(), PetscMallocDumpLog()
501 @*/
502 PetscErrorCode PETSCSYS_DLLEXPORT PetscMallocSetDumpLog(void)
503 {
504   PetscErrorCode ierr;
505 
506   PetscFunctionBegin;
507   PetscLogMalloc = 0;
508   ierr = PetscMemorySetGetMaximumUsage();CHKERRQ(ierr);
509   PetscFunctionReturn(0);
510 }
511 
512 #undef __FUNCT__
513 #define __FUNCT__ "PetscMallocDumpLog"
514 /*@C
515     PetscMallocDumpLog - Dumps the log of all calls to PetscMalloc(); also calls
516        PetscMemoryGetMaximumUsage()
517 
518     Collective on PETSC_COMM_WORLD
519 
520     Input Parameter:
521 .   fp - file pointer; or PETSC_NULL
522 
523     Options Database Key:
524 .  -malloc_log - Activates PetscMallocDumpLog()
525 
526     Level: advanced
527 
528    Fortran Note:
529    The calling sequence in Fortran is PetscMallocDumpLog(integer ierr)
530    The fp defaults to stdout.
531 
532 .seealso: PetscMallocGetCurrentUsage(), PetscMallocDump(), PetscMallocSetDumpLog()
533 @*/
534 PetscErrorCode PETSCSYS_DLLEXPORT PetscMallocDumpLog(FILE *fp)
535 {
536   PetscInt       i,j,n,dummy,*perm;
537   size_t         *shortlength;
538   int            *shortcount,err;
539   PetscMPIInt    rank,size,tag = 1212 /* very bad programming */;
540   PetscBool      match;
541   const char     **shortfunction;
542   PetscLogDouble rss;
543   MPI_Status     status;
544   PetscErrorCode ierr;
545 
546   PetscFunctionBegin;
547   ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr);
548   ierr = MPI_Comm_size(MPI_COMM_WORLD,&size);CHKERRQ(ierr);
549   /*
550        Try to get the data printed in order by processor. This will only sometimes work
551   */
552   err = fflush(fp);
553   if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
554 
555   ierr = MPI_Barrier(MPI_COMM_WORLD);CHKERRQ(ierr);
556   if (rank) {
557     ierr = MPI_Recv(&dummy,1,MPIU_INT,rank-1,tag,MPI_COMM_WORLD,&status);CHKERRQ(ierr);
558   }
559 
560   if (!fp) fp = PETSC_STDOUT;
561   ierr = PetscMemoryGetMaximumUsage(&rss);CHKERRQ(ierr);
562   if (rss) {
563     ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n",rank,(PetscLogDouble)TRMaxMem,rss);CHKERRQ(ierr);
564   } else {
565     ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n",rank,(PetscLogDouble)TRMaxMem);CHKERRQ(ierr);
566   }
567   if (PetscLogMalloc < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"PetscMallocDumpLog() called without call to PetscMallocSetDumpLog() this is often due to\n                      setting the option -malloc_log AFTER PetscInitialize() with PetscOptionsInsert() or PetscOptionsInsertFile()");
568   shortcount       = (int*)malloc(PetscLogMalloc*sizeof(int));if (!shortcount) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
569   shortlength      = (size_t*)malloc(PetscLogMalloc*sizeof(size_t));if (!shortlength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
570   shortfunction    = (const char**)malloc(PetscLogMalloc*sizeof(char *));if (!shortfunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
571   shortfunction[0] = PetscLogMallocFunction[0];
572   shortlength[0]   = PetscLogMallocLength[0];
573   shortcount[0]    = 0;
574   n = 1;
575   for (i=1; i<PetscLogMalloc; i++) {
576     for (j=0; j<n; j++) {
577       ierr = PetscStrcmp(shortfunction[j],PetscLogMallocFunction[i],&match);CHKERRQ(ierr);
578       if (match) {
579         shortlength[j] += PetscLogMallocLength[i];
580         shortcount[j]++;
581         goto foundit;
582       }
583     }
584     shortfunction[n] = PetscLogMallocFunction[i];
585     shortlength[n]   = PetscLogMallocLength[i];
586     shortcount[n]    = 1;
587     n++;
588     foundit:;
589   }
590 
591   perm = (PetscInt*)malloc(n*sizeof(PetscInt));if (!perm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
592   for (i=0; i<n; i++) perm[i] = i;
593   ierr = PetscSortStrWithPermutation(n,(const char **)shortfunction,perm);CHKERRQ(ierr);
594 
595   ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] Memory usage sorted by function\n",rank);CHKERRQ(ierr);
596   for (i=0; i<n; i++) {
597     ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] %d %.0f %s()\n",rank,shortcount[perm[i]],(PetscLogDouble)shortlength[perm[i]],shortfunction[perm[i]]);CHKERRQ(ierr);
598   }
599   free(perm);
600   free(shortlength);
601   free(shortcount);
602   free((char **)shortfunction);
603   err = fflush(fp);
604   if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
605   if (rank != size-1) {
606     ierr = MPI_Send(&dummy,1,MPIU_INT,rank+1,tag,MPI_COMM_WORLD);CHKERRQ(ierr);
607   }
608   PetscFunctionReturn(0);
609 }
610 
611 /* ---------------------------------------------------------------------------- */
612 
613 #undef __FUNCT__
614 #define __FUNCT__ "PetscMallocDebug"
615 /*@C
616     PetscMallocDebug - Turns on/off debugging for the memory management routines.
617 
618     Not Collective
619 
620     Input Parameter:
621 .   level - PETSC_TRUE or PETSC_FALSE
622 
623    Level: intermediate
624 
625 .seealso: CHKMEMQ(), PetscMallocValidate()
626 @*/
627 PetscErrorCode PETSCSYS_DLLEXPORT PetscMallocDebug(PetscBool  level)
628 {
629   PetscFunctionBegin;
630   TRdebugLevel = level;
631   PetscFunctionReturn(0);
632 }
633