Changeset: 465cc1be670d for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=465cc1be670d
Modified Files:
clients/mapiclient/tachograph.c
monetdb5/mal/mal.c
monetdb5/mal/mal.h
monetdb5/mal/mal_listing.c
monetdb5/mal/mal_listing.h
monetdb5/mal/mal_profiler.c
monetdb5/optimizer/Makefile.ag
monetdb5/optimizer/opt_pipes.c
monetdb5/optimizer/opt_prelude.c
monetdb5/optimizer/opt_prelude.h
monetdb5/optimizer/opt_support.c
monetdb5/optimizer/opt_support.h
monetdb5/optimizer/opt_wrapper.c
monetdb5/optimizer/optimizer.mal
tools/mserver/mserver5.c
Branch: profiler
Log Message:
JSON based profiling
First step into moving performance monitoring
to the (less humanreadable) JSON format structure.
diffs (truncated from 602 to 300 lines):
diff --git a/clients/mapiclient/tachograph.c b/clients/mapiclient/tachograph.c
--- a/clients/mapiclient/tachograph.c
+++ b/clients/mapiclient/tachograph.c
@@ -750,6 +750,7 @@ update(EventRecord *ev)
fprintf(tachojson,"{\n");
fprintf(tachojson,"\"qid\":\"%s\",\n",currentfunction?currentfunction:"");
fprintf(tachojson,"\"tag\":%d,\n",ev->tag);
+ fprintf(tachojson,"\"thread\":%d,\n",ev->thread);
fprintf(tachojson,"\"pc\":%d,\n",ev->pc);
fprintf(tachojson,"\"time\": "LLFMT",\n",ev->clkticks);
fprintf(tachojson,"\"status\": \"done\",\n");
diff --git a/monetdb5/mal/mal.c b/monetdb5/mal/mal.c
--- a/monetdb5/mal/mal.c
+++ b/monetdb5/mal/mal.c
@@ -12,7 +12,7 @@
char monet_cwd[PATHLENGTH] = { 0 };
size_t monet_memory;
-char monet_characteristics[PATHLENGTH];
+char monetdb_characteristics[PATHLENGTH];
int mal_trace; /* enable profile events on console */
#ifdef HAVE_HGE
int have_hge;
diff --git a/monetdb5/mal/mal.h b/monetdb5/mal/mal.h
--- a/monetdb5/mal/mal.h
+++ b/monetdb5/mal/mal.h
@@ -48,7 +48,7 @@
mal_export char monet_cwd[PATHLENGTH];
mal_export size_t monet_memory;
-mal_export char monet_characteristics[PATHLENGTH];
+mal_export char monetdb_characteristics[PATHLENGTH];
mal_export lng memorypool; /* memory claimed by
concurrent threads */
mal_export int memoryclaims; /* number of threads active
with expensive operations */
mal_export int mal_trace; /* enable profile events on
console */
diff --git a/monetdb5/mal/mal_listing.c b/monetdb5/mal/mal_listing.c
--- a/monetdb5/mal/mal_listing.c
+++ b/monetdb5/mal/mal_listing.c
@@ -16,6 +16,7 @@
#include "mal_utils.h"
#include "mal_exception.h"
#include "mal_listing.h"
+#include "mal_properties.h"
/*
* Since MAL programs can be created on the fly by linked-in query
@@ -376,6 +377,115 @@ instruction2str(MalBlkPtr mb, MalStkPtr
return s;
}
+/* the MAL beautifier is meant to simplify correlation of MAL variables and
+ * the columns in the underlying database.
+ * If the status is set, then we consider the instruction DONE and the result
variables
+ * should be shown as well.
+ */
+static str
+beautyTerm(MalBlkPtr mb, MalStkPtr stk, InstrPtr p, int idx)
+{
+ str s, nme;
+ BAT *b;
+ ValRecord *val;
+ //VarPtr v;
+ char *cv =0;
+ int varid = getArg(p,idx);
+
+ s= GDKmalloc(BUFSIZ);
+ *s = 0;
+
+ if( isVarConstant(mb,varid) ){
+ val =&getVarConstant(mb, varid);
+ VALformat(&cv, val);
+ snprintf(s,BUFSIZ,"%s",cv);
+ if(cv)
+ GDKfree(cv);
+ } else {
+ val = &stk->stk[varid];
+ VALformat(&cv, val);
+ //v = varGetProp(mb, varid, PropertyIndex("schematablecolumn"));
+ nme = getVarName(mb, varid);
+ if ( isaBatType(getArgType(mb,p,idx))){
+ b = BBPquickdesc(abs(stk->stk[varid].val.ival),TRUE);
+ snprintf(s,BUFSIZ,"%s["BUNFMT"]",nme, b?BATcount(b):0);
+ } else
+ snprintf(s,BUFSIZ,"%s",nme);
+ GDKfree(nme);
+ }
+ return s;
+}
+
+str
+instruction2beauty(MalBlkPtr mb, MalStkPtr stk, InstrPtr p, int done)
+{
+ int i;
+ str base, s, t, nme;
+ size_t len= (mb->stop < 1000? 1000: mb->stop) * 128 /* max realistic
line length estimate */;
+
+ base = s = GDKmalloc(len);
+ if ( s == NULL)
+ return s;
+ *s =0;
+ t=s;
+ if (p->token == REMsymbol)
+ return base;
+ // handle the result variables
+ if( done ){
+ for (i = 0; i < p->retc; i++)
+ if (!getVarTmp(mb, getArg(p, i)) || isVarUsed(mb,
getArg(p, i)) || isVarUDFtype(mb,getArg(p,i)))
+ break;
+
+ if (i == p->retc) // no result arguments
+ goto beauty_end;
+
+ /* display optional multi-assignment list */
+ if (p->retc > 1)
+ *t++ = '(';
+
+ for (i = 0; i < p->retc; i++) {
+ nme = beautyTerm(mb, stk, p,i);
+ snprintf(t,(len-(t-base)), "%s", nme);
+ GDKfree(nme);
+ advance(t,base,len);
+ if (i < p->retc - 1)
+ *t++ = ',';
+ }
+ if (p->retc > 1)
+ *t++ = ')';
+
+ }
+ beauty_end:
+ // handle the instruction mapping
+
+ advance(t,base,len);
+ nme = 0;
+ //nme = varGetPropStr(mb, getArg(p,0), PropertyIndex("beautyoperator"));
+ if( nme){
+ snprintf(t, (len-(t-base)),"%s", nme);
+ GDKfree(nme);
+ } else
+ snprintf(t, (len-(t-base)),"%s.%s", getModuleId(p),
getFunctionId(p));
+ advance(t,base,len);
+
+ // handle the arguments, constants should be shown including their
non-default type
+ /* display optional multi-assignment list */
+ *t++ = '(';
+ for (i = 0; i < p->retc; i++) {
+ nme = beautyTerm(mb, stk, p,i);
+ snprintf(t,(len-(t-base)), "%s", nme);
+ GDKfree(nme);
+ advance(t,base,len);
+ if (i < p->retc - 1)
+ *t++ = ',';
+ }
+ *t++ = ')';
+
+ if (t >= s + len)
+ throw(MAL,"instruction2str:","instruction too long");
+ return s;
+}
+
/* Remote execution of MAL calls for more type/property information to be
exchanged */
str
mal2str(MalBlkPtr mb, int first, int last)
diff --git a/monetdb5/mal/mal_listing.h b/monetdb5/mal/mal_listing.h
--- a/monetdb5/mal/mal_listing.h
+++ b/monetdb5/mal/mal_listing.h
@@ -21,6 +21,7 @@ mal_export void printInstruction(stream
mal_export str instructionCall(MalBlkPtr mb, InstrPtr p, str s, str base,
size_t len);
mal_export void promptInstruction(stream *fd, MalBlkPtr mb, MalStkPtr stk,
InstrPtr p, int flg);
mal_export str instruction2str(MalBlkPtr mb, MalStkPtr stl, InstrPtr p, int
hidden);
+mal_export str instruction2beauty(MalBlkPtr mb, MalStkPtr stl, InstrPtr p, int
done);
mal_export str mal2str(MalBlkPtr mb, int first, int last);
mal_export void showMalBlkHistory(stream *out, MalBlkPtr mb);
diff --git a/monetdb5/mal/mal_profiler.c b/monetdb5/mal/mal_profiler.c
--- a/monetdb5/mal/mal_profiler.c
+++ b/monetdb5/mal/mal_profiler.c
@@ -25,10 +25,12 @@ stream *eventstream = 0;
static int offlineProfiling = FALSE;
static int cachedProfiling = FALSE;
+static int jsonrendering = TRUE;
static str myname = 0;
static oid user = 0;
static void offlineProfilerEvent(MalBlkPtr mb, MalStkPtr stk, InstrPtr pc, int
start, char *alter, char *msg);
+static void offlineProfilerEventJSON(MalBlkPtr mb, MalStkPtr stk, InstrPtr pc,
int start, char *alter, char *msg);
static void cachedProfilerEvent(MalBlkPtr mb, MalStkPtr stk, InstrPtr pc);
static int initTrace(void);
@@ -56,6 +58,8 @@ offlineProfilerHeader(void)
if (eventstream == NULL)
return ;
+ if (jsonrendering)
+ return;
lognew();
logadd("# ");
@@ -106,7 +110,46 @@ static void logsend(char *logbuffer)
error= mnstr_flush(eventstream);
MT_lock_unset(&mal_profileLock, "logsend");
if( showsystem)
- offlineProfilerEvent(0, 0, 0, 0, "system",
monet_characteristics);
+ offlineProfilerEvent(0, 0, 0, 0, "system",
monetdb_characteristics);
+ if ( error) stopProfiler();
+ }
+}
+
+static void logsendJSON(char *logbuffer)
+{ int error=0;
+ char buf[BUFSIZ], *s;
+ size_t len, out;
+
+ if (eventstream) {
+ MT_lock_set(&mal_profileLock, "logsendJSON");
+ if( eventcounter == 0){
+ snprintf(buf,BUFSIZ,"%s\n",monetdb_characteristics);
+ len = strlen(buf);
+ out = mnstr_write(eventstream, buf, 1, len);
+ if( out != len){
+ MT_lock_unset(&mal_profileLock, "logsendJSON");
+ stopProfiler();
+ return;
+ }
+ }
+ eventcounter++;
+ snprintf(buf,BUFSIZ,"%d",eventcounter);
+ s = strchr(logbuffer,(int) ':');
+ if( s == NULL){
+ MT_lock_unset(&mal_profileLock, "logsendJSON");
+ return;
+ }
+
+ strncpy(s+1, buf,strlen(buf));
+ len = strlen(logbuffer);
+ out= mnstr_write(eventstream, logbuffer, 1, len);
+ if( out != len){
+ MT_lock_unset(&mal_profileLock, "logsendJSON");
+ stopProfiler();
+ return;
+ }
+ error= mnstr_flush(eventstream);
+ MT_lock_unset(&mal_profileLock, "logsendJSON");
if ( error) stopProfiler();
}
}
@@ -126,8 +169,10 @@ profilerEvent(oid usr, MalBlkPtr mb, Mal
if (pci == NULL) return;
if (getModuleId(pci) == myname) // ignore profiler commands from
monitoring
return;
- if (offlineProfiling)
+ if (offlineProfiling && !jsonrendering)
offlineProfilerEvent(mb, stk, pci, start,0,0);
+ if (offlineProfiling && jsonrendering)
+ offlineProfilerEventJSON(mb, stk, pci, start,0,0);
if (cachedProfiling && !start )
cachedProfilerEvent(mb, stk, pci);
if ( start && pci->pc ==0)
@@ -253,6 +298,158 @@ offlineProfilerEvent(MalBlkPtr mb, MalSt
logadd("\t]\n"); // end marker
logsend(logbuffer);
}
+
+/* JSON rendering method of performance data. Using the table header as tag,
breaking the complex fields. Example:
+ */
+void
+offlineProfilerEventJSON(MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, int start,
char *alter, char *msg)
+{
+ char logbuffer[LOGLEN], *logbase;
+ int loglen;
+ char ctm[26];
+ time_t clk;
+ struct timeval clock;
+ str stmt, c;
+ char *tbuf;
+ str stmtq;
+
+ if (eventstream == NULL)
+ return ;
+ if (jsonrendering == FALSE)
+ return ;
+
+ if( start) // show when instruction was started
+ clock = pci->clock;
+ else
+ gettimeofday(&clock, NULL);
+ clk = clock.tv_sec;
+
+ /* make basic profile event tuple */
+ lognew();
+ logadd("{ \"event\": ,\n"); // fill in later with the event
counter
+
+ /* without this cast, compilation on Windows fails with
+ * argument of type "long *" is incompatible with parameter of type
"const time_t={__time64_t={__int64}} *"
+ */
+#ifdef HAVE_CTIME_R3
+ tbuf = ctime_r(&clk, ctm, sizeof(ctm));
+#else
+#ifdef HAVE_CTIME_R
+ tbuf = ctime_r(&clk, ctm);
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list