From 229d4744e2b4c98449a5d2e42ee6733d18aff837 Mon Sep 17 00:00:00 2001 From: Randell Jesup Date: Wed, 18 Jan 2012 00:11:00 -0500 Subject: [PATCH] Bug 712224: Make jprof generate output for 'cleopatra' backend. rs=dbaron DONTBUILD --- tools/jprof/leaky.cpp | 134 ++++++++++++++++++++++++++++-------------- tools/jprof/leaky.h | 1 + 2 files changed, 90 insertions(+), 45 deletions(-) diff --git a/tools/jprof/leaky.cpp b/tools/jprof/leaky.cpp index a593e9ddbac..26e9f9c605a 100644 --- a/tools/jprof/leaky.cpp +++ b/tools/jprof/leaky.cpp @@ -155,6 +155,7 @@ leaky::leaky() showThreads = false; stackDepth = 100000; onlyThread = 0; + cleo = false; mappedLogFile = -1; firstLogEntry = lastLogEntry = 0; @@ -179,7 +180,7 @@ leaky::~leaky() void leaky::usageError() { - fprintf(stderr, "Usage: %s [-v] [-t] [-e exclude] [-i include] [-s stackdepth] [--last] [--all] [--start n [--end m]] [--output-dir dir] prog log [log2 ...]\n", (char*) applicationName); + fprintf(stderr, "Usage: %s [-v] [-t] [-e exclude] [-i include] [-s stackdepth] [--last] [--all] [--start n [--end m]] [--cleo] [--output-dir dir] prog log [log2 ...]\n", (char*) applicationName); fprintf(stderr, "\t-v: verbose\n" "\t-t | --threads: split threads\n" @@ -189,6 +190,7 @@ void leaky::usageError() "\t-s stackdepth: Limit depth looked at from captured stack frames\n" "\t--last: only profile the last capture section\n" "\t--start n [--end m]: profile n to m (or end) capture sections\n" + "\t--cleo: format output for 'cleopatra' display\n" "\t--output-dir dir: write output files to dir\n" "\tIf there's one log, output goes to stdout unless --output-dir is set\n" "\tIf there are more than one log, output files will be named with .html added\n" @@ -202,6 +204,7 @@ static struct option longopts[] = { { "last", 0, NULL, 'l' }, { "start", 1, NULL, 'x' }, { "end", 1, NULL, 'n' }, + { "cleo",0, NULL, 'c' }, { "output-dir", 1, NULL, 'd' }, { NULL, 0, NULL, 0 }, }; @@ -222,6 +225,7 @@ void leaky::initialize(int argc, char** argv) onlyThread = 0; output_dir = NULL; + cleo = false; // XXX tons of cruft here left over from tracemalloc // XXX The -- options shouldn't need short versions, or they should be documented @@ -237,6 +241,9 @@ void leaky::initialize(int argc, char** argv) case 'A': // not implemented showAddress = true; break; + case 'c': + cleo = true; + break; case 'd': output_dir = optarg; // reference to an argv pointer break; @@ -439,20 +446,24 @@ void leaky::open(char *logFile) fprintf(stderr,"Done collecting: sections %d: first=%p, last=%p, numThreads=%d\n", section,(void*)firstLogEntry,(void*)lastLogEntry,numThreads); - fprintf(outputfd,"Jprof Profile Report\n"); - fprintf(outputfd,"

Jprof Profile Report

\n"); + if (!cleo) { + fprintf(outputfd,"Jprof Profile Report\n"); + fprintf(outputfd,"

Jprof Profile Report

\n"); + } if (showThreads) { fprintf(stderr,"Num threads %d\n",numThreads); - fprintf(outputfd,"
Threads:

\n");
-    for (int i=0; i%d  ",
-              threadArray[i],threadArray[i]);
+    if (!cleo) {
+      fprintf(outputfd,"
Threads:

\n");
+      for (int i=0; i%d  ",
+                threadArray[i],threadArray[i]);
+      }
+      fprintf(outputfd,"
"); } - fprintf(outputfd,"
"); for (int i=0; i\n"); + if (!cleo) + fprintf(outputfd,"\n"); } //---------------------------------------------------------------------- @@ -762,6 +774,9 @@ void leaky::analyze(int thread) // from the prior stacktrace. memset(flagArray, -1, sizeof(flagArray[0])*usefulSymbols); + if (cleo) + fprintf(outputfd,"m-Start\n"); + // This loop walks through all the call stacks we recorded // --last, --start and --end can restrict it, as can excludes/includes stacks = 0; @@ -777,49 +792,78 @@ void leaky::analyze(int thread) ++stacks; // How many stack frames did we collect - // This loop walks through every symbol in the call stack. By walking it - // backwards we know who called the function when we get there. u_int n = (lep->numpcs < stackDepth) ? lep->numpcs : stackDepth; char** pcp = &lep->pcs[n-1]; int idx=-1, parrentIdx=-1; // Init idx incase n==0 - for (int i=n-1; i>=0; --i, --pcp) { - idx = findSymbolIndex(reinterpret_cast(*pcp)); + if (cleo) { + // This loop walks through every symbol in the call stack. By walking it + // backwards we know who called the function when we get there. + char type = 's'; + for (int i=n-1; i>=0; --i, --pcp) { + idx = findSymbolIndex(reinterpret_cast(*pcp)); - if(idx>=0) { - // Skip over bogus __restore_rt frames that realtime profiling - // can introduce. - if (i > 0 && !strcmp(externalSymbols[idx].name, "__restore_rt")) { - --pcp; - --i; - idx = findSymbolIndex(reinterpret_cast(*pcp)); - if (idx < 0) { - continue; - } - } - - // If we have not seen this symbol before count it and mark it as seen - if(flagArray[idx]!=stacks && ((flagArray[idx]=stacks) || true)) { - ++countArray[idx]; - } - - // We know who we are and we know who our parrent is. Count this - if(parrentIdx>=0) { - externalSymbols[parrentIdx].regChild(idx); - externalSymbols[idx].regParrent(parrentIdx); - } - // inside if() so an unknown in the middle of a stack won't break - // the link! - parrentIdx=idx; + if(idx>=0) { + // Skip over bogus __restore_rt frames that realtime profiling + // can introduce. + if (i > 0 && !strcmp(externalSymbols[idx].name, "__restore_rt")) { + --pcp; + --i; + idx = findSymbolIndex(reinterpret_cast(*pcp)); + if (idx < 0) { + continue; + } + } + Symbol *sp=&externalSymbols[idx]; + char *symname = htmlify(sp->name); + fprintf(outputfd,"%c-%s\n",type,symname); + delete [] symname; + } + // else can't find symbol - ignore + type = 'c'; + } + } else { + // This loop walks through every symbol in the call stack. By walking it + // backwards we know who called the function when we get there. + for (int i=n-1; i>=0; --i, --pcp) { + idx = findSymbolIndex(reinterpret_cast(*pcp)); + + if(idx>=0) { + // Skip over bogus __restore_rt frames that realtime profiling + // can introduce. + if (i > 0 && !strcmp(externalSymbols[idx].name, "__restore_rt")) { + --pcp; + --i; + idx = findSymbolIndex(reinterpret_cast(*pcp)); + if (idx < 0) { + continue; + } + } + + // If we have not seen this symbol before count it and mark it as seen + if(flagArray[idx]!=stacks && ((flagArray[idx]=stacks) || true)) { + ++countArray[idx]; + } + + // We know who we are and we know who our parrent is. Count this + if(parrentIdx>=0) { + externalSymbols[parrentIdx].regChild(idx); + externalSymbols[idx].regParrent(parrentIdx); + } + // inside if() so an unknown in the middle of a stack won't break + // the link! + parrentIdx=idx; + } + } + + // idx should be the function that we were in when we received the signal. + if(idx>=0) { + ++externalSymbols[idx].timerHit; } - } - // idx should be the function that we were in when we received the signal. - if(idx>=0) { - ++externalSymbols[idx].timerHit; } } - - generateReportHTML(outputfd, countArray, stacks, thread); + if (!cleo) + generateReportHTML(outputfd, countArray, stacks, thread); } void FunctionCount::printReport(FILE *fp, leaky *lk, int parent, int total) diff --git a/tools/jprof/leaky.h b/tools/jprof/leaky.h index 4e678beff4c..45904b063ea 100644 --- a/tools/jprof/leaky.h +++ b/tools/jprof/leaky.h @@ -94,6 +94,7 @@ struct leaky { bool quiet; bool showAddress; bool showThreads; + bool cleo; u_int stackDepth; int onlyThread; char* output_dir;