doc: Add serial to list of ci file reserved words
[charm.git] / src / ck-perf / trace-memory.C
index 437b3da150b27971f75483e118c8092b1616d4fd..1d7e480276f353a0ab0362203d6c4a8624ed30a8 100644 (file)
@@ -1,10 +1,12 @@
 #include "trace-memory.h"
 
-#define DefaultBufferSize  1000000
+#define DefaultBufferSize  10000
 
 #define DEBUGF(x) // CmiPrintf x
 
 CkpvStaticDeclare(TraceMemory*, _trace);
+extern "C" void memory_trace_all_existing_mallocs();
+extern "C" int get_memory_allocated_user_total();
 
 /**
   For each TraceFoo module, _createTraceFoo() must be defined.
@@ -16,37 +18,60 @@ void _createTracememory(char **argv)
   CkpvInitialize(TraceMemory*, _trace);
   CkpvAccess(_trace) = new TraceMemory(argv);
   CkpvAccess(_traces)->addTrace(CkpvAccess(_trace));
+  /* Since we started after the beginning of the program, we missed a bunch of
+   * allocations. We cannot record what was allocated and then deleted, but we
+   * can still record all the memory that is still allocated.
+   */
 }
 
-MemEntry::MemEntry() : type(0), where(0), size(0) { }
+MemEntry::MemEntry() : type(0), where(0), size(0), stackSize(0) { }
 
 void MemEntry::write(FILE *fp) {
-  fprintf(fp, "%d %p", type, where);
-  if (type == MEMORY_MALLOC) fprintf(fp, " %d", size);
+  if (type == BEGIN_TRACE) {
+    fprintf(fp, "%d %d\n", type, size);
+    return;
+  }
+  fprintf(fp, "%d %p %d", type, where, size);
+  if (type == MEMORY_MALLOC) {
+    fprintf(fp, " %d", stackSize);
+    void **stack = (void**)(this+1);
+    for (int i=stackSize-1; i>=0; --i) {
+      fprintf(fp, " %p", stack[i]);
+    }
+  }
   fprintf(fp, "\n");
 }
 
 TraceMemory::TraceMemory(char **argv) {
   usedBuffer = 0;
   firstTime = 1;
+  traceDisabled = false;
   logBufSize = DefaultBufferSize;
   if (CmiGetArgIntDesc(argv,"+memlogsize",&logBufSize, 
-                      "Log entries to buffer per I/O")) {
+                      "Log buffer size (in kB)")) {
     if (CkMyPe() == 0) {
-      CmiPrintf("Trace: logsize: %d\n", logBufSize);
+      CmiPrintf("Trace: logsize: %d kB\n", logBufSize);
     }
   }
-  logBuffer = new MemEntry[logBufSize];
+  recordStack = false;
+  if (CmiGetArgFlagDesc(argv,"+recordStack",
+               "Record stack trace for malloc")) {
+    recordStack = true;
+  }
+  logBufSize *= 1024;
+  logBuffer = (char *) ::malloc(logBufSize);
 }
 
-inline void TraceMemory::checkFlush() {
-  if (usedBuffer == logBufSize) {
+inline void TraceMemory::checkFlush(int increment) {
+  if (usedBuffer+increment >= logBufSize) {
     flush();
   }
 }
 
 inline void TraceMemory::flush() {
-  char *mode;
+  traceDisabled = true;
+  //CmiPrintf("[%d] TraceMemory::flush %d\n",CmiMyPe(),usedBuffer);
+  const char *mode;
   if (firstTime) mode = "w";
   else mode = "a";
   firstTime = 0;
@@ -60,21 +85,44 @@ inline void TraceMemory::flush() {
   if (!fp) {
     CmiAbort("Cannot open file for Memory log writing\n");
   }
-  for (int i=0; i<usedBuffer; ++i) logBuffer[i].write(fp);
+  //fprintf(fp, "begin flush\n");
+  for (int i=0; i<usedBuffer; i += sizeof(MemEntry) + ((MemEntry*)&logBuffer[i])->stackSize*sizeof(void*)) {
+    ((MemEntry*)&logBuffer[i])->write(fp);
+  }
+  //fprintf(fp, "end flush\n");
   fclose(fp);
   usedBuffer = 0;
+  traceDisabled = false;
 }
 
 void TraceMemory::traceClose() {
   flush();
 }
 
-void TraceMemory::malloc(void *where, int size) {
-  logBuffer[usedBuffer++].set(MEMORY_MALLOC, where, size);
-  checkFlush();
+void TraceMemory::traceBegin() {
+  int increment = sizeof(MemEntry);
+  checkFlush(increment);
+  ((MemEntry*)&logBuffer[usedBuffer])->set(BEGIN_TRACE, 0, get_memory_allocated_user_total());
+  usedBuffer += increment;
 }
 
-void TraceMemory::free(void *where) {
-  logBuffer[usedBuffer++].set(MEMORY_FREE, where);
-  checkFlush();
+void TraceMemory::malloc(void *where, int size, void **stack, int stackSize) {
+  if (!traceDisabled) {
+    int increment = sizeof(MemEntry) + (recordStack ? stackSize*sizeof(void*) : 0);
+    checkFlush(increment);
+    ((MemEntry*)&logBuffer[usedBuffer])->set(MEMORY_MALLOC, where, size);
+    if (recordStack) ((MemEntry*)&logBuffer[usedBuffer])->setStack(stackSize, stack);
+    usedBuffer += increment;
+    //CmiPrintf("[%d] TraceMemory::malloc  %d  (%p)\n",CmiMyPe(),usedBuffer,where);
+  }
+}
+
+void TraceMemory::free(void *where, int size) {
+  if (!traceDisabled) {
+    int increment = sizeof(MemEntry);
+    checkFlush(increment);
+    ((MemEntry*)&logBuffer[usedBuffer])->set(MEMORY_FREE, where, size);
+    usedBuffer += increment;
+    //CmiPrintf("[%d] TraceMemory::free    %d  (%p)\n",CmiMyPe(),usedBuffer,where);
+  }
 }