openenvutils/commandshell/shell/src/modules/zprof.c
changeset 0 2e3d3ce01487
child 4 0fdb7f6b0309
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/openenvutils/commandshell/shell/src/modules/zprof.c	Tue Feb 02 10:12:00 2010 +0200
@@ -0,0 +1,344 @@
+//
+// © Portions Copyright (c) Symbian Software Ltd 2007. All rights reserved.
+//
+/*
+ * zprof.c - a shell function profiling module for zsh
+ *
+ * This file is part of zsh, the Z shell.
+ *
+ * Copyright (c) 1996-1997 Sven Wischnowsky
+ * All rights reserved.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and to distribute modified versions of this software for any
+ * purpose, provided that the above copyright notice and the following
+ * two paragraphs appear in all copies of this software.
+ *
+ * In no event shall Sven Wischnowsky or the Zsh Development Group be liable
+ * to any party for direct, indirect, special, incidental, or consequential
+ * damages arising out of the use of this software and its documentation,
+ * even if Sven Wischnowsky and the Zsh Development Group have been advised of
+ * the possibility of such damage.
+ *
+ * Sven Wischnowsky and the Zsh Development Group specifically disclaim any
+ * warranties, including, but not limited to, the implied warranties of
+ * merchantability and fitness for a particular purpose.  The software
+ * provided hereunder is on an "as is" basis, and Sven Wischnowsky and the
+ * Zsh Development Group have no obligation to provide maintenance,
+ * support, updates, enhancements, or modifications.
+ *
+ */
+#include "zprof.mdh"
+#include "zprof.pro"
+
+#include <sys/time.h>
+#include <unistd.h>
+
+#ifdef __SYMBIAN32__
+#ifdef __WINSCW__
+#pragma warn_unusedarg off
+#pragma warn_possunwant off
+#endif//__WINSCW__
+#endif//__SYMBIAN32__
+
+typedef struct pfunc *Pfunc;
+
+struct pfunc {
+    Pfunc next;
+    char *name;
+    long calls;
+    double time;
+    double self;
+    long num;
+};
+
+typedef struct sfunc *Sfunc;
+
+struct sfunc {
+    Pfunc p;
+    Sfunc prev;
+    double beg;
+};
+
+typedef struct parc *Parc;
+
+struct parc {
+    Parc next;
+    Pfunc from;
+    Pfunc to;
+    long calls;
+    double time;
+    double self;
+};
+
+static Pfunc calls;
+static int ncalls;
+static Parc arcs;
+static int narcs;
+static Sfunc stack;
+static Module zprof_module;
+
+static void
+freepfuncs(Pfunc f)
+{
+    Pfunc n;
+
+    for (; f; f = n) {
+	n = f->next;
+	zsfree(f->name);
+	zfree(f, sizeof(*f));
+    }
+}
+
+static void
+freeparcs(Parc a)
+{
+    Parc n;
+
+    for (; a; a = n) {
+	n = a->next;
+	zfree(a, sizeof(*a));
+    }
+}
+
+static Pfunc
+findpfunc(char *name)
+{
+    Pfunc f;
+
+    for (f = calls; f; f = f->next)
+	if (!strcmp(name, f->name))
+	    return f;
+
+    return NULL;
+}
+
+static Parc
+findparc(Pfunc f, Pfunc t)
+{
+    Parc a;
+
+    for (a = arcs; a; a = a->next)
+	if (a->from == f && a->to == t)
+	    return a;
+
+    return NULL;
+}
+
+static int
+cmpsfuncs(Pfunc *a, Pfunc *b)
+{
+    return ((*a)->self > (*b)->self ? -1 : ((*a)->self != (*b)->self));
+}
+
+static int
+cmptfuncs(Pfunc *a, Pfunc *b)
+{
+    return ((*a)->time > (*b)->time ? -1 : ((*a)->time != (*b)->time));
+}
+
+static int
+cmpparcs(Parc *a, Parc *b)
+{
+    return ((*a)->time > (*b)->time ? -1 : ((*a)->time != (*b)->time));
+}
+
+static int
+bin_zprof(UNUSED(char *nam), UNUSED(char **args), Options ops, UNUSED(int func))
+{
+    if (OPT_ISSET(ops,'c')) {
+	freepfuncs(calls);
+	calls = NULL;
+	ncalls = 0;
+	freeparcs(arcs);
+	arcs = NULL;
+	narcs = 0;
+    } else {
+	VARARR(Pfunc, fs, (ncalls + 1));
+	Pfunc f, *fp;
+	VARARR(Parc, as, (narcs + 1));
+	Parc a, *ap;
+	long i;
+	double total;
+
+	for (total = 0.0, f = calls, fp = fs; f; f = f->next, fp++) {
+	    *fp = f;
+	    total += f->self;
+	}
+	*fp = NULL;
+	for (a = arcs, ap = as; a; a = a->next, ap++)
+	    *ap = a;
+	*ap = NULL;
+
+	qsort(fs, ncalls, sizeof(f),
+	      (int (*) _((const void *, const void *))) cmpsfuncs);
+	qsort(as, narcs, sizeof(a),
+	      (int (*) _((const void *, const void *))) cmpparcs);
+
+	printf("num  calls                time                       self            name\n-----------------------------------------------------------------------------------\n");
+	for (fp = fs, i = 1; *fp; fp++, i++) {
+	    printf("%2ld) %4ld       %8.2f %8.2f  %6.2f%%  %8.2f %8.2f  %6.2f%%  %s\n",
+		   ((*fp)->num = i),
+		   (*fp)->calls,
+		   (*fp)->time, (*fp)->time / ((double) (*fp)->calls),
+		   ((*fp)->time / total) * 100.0,
+		   (*fp)->self, (*fp)->self / ((double) (*fp)->calls),
+		   ((*fp)->self / total) * 100.0,
+		   (*fp)->name);
+	}
+	qsort(fs, ncalls, sizeof(f),
+	      (int (*) _((const void *, const void *))) cmptfuncs);
+
+	for (fp = fs; *fp; fp++) {
+	    printf("\n-----------------------------------------------------------------------------------\n\n");
+	    for (ap = as; *ap; ap++)
+		if ((*ap)->to == *fp) {
+		    printf("    %4ld/%-4ld  %8.2f %8.2f  %6.2f%%  %8.2f %8.2f             %s [%ld]\n",
+			   (*ap)->calls, (*fp)->calls,
+			   (*ap)->time, (*ap)->time / ((double) (*ap)->calls),
+			   ((*ap)->time / total) * 100.0,
+			   (*ap)->self, (*ap)->self / ((double) (*ap)->calls),
+			   (*ap)->from->name, (*ap)->from->num);
+		}
+	    printf("%2ld) %4ld       %8.2f %8.2f  %6.2f%%  %8.2f %8.2f  %6.2f%%  %s\n",
+		   (*fp)->num, (*fp)->calls,
+		   (*fp)->time, (*fp)->time / ((double) (*fp)->calls),
+		   ((*fp)->time / total) * 100.0,
+		   (*fp)->self, (*fp)->self / ((double) (*fp)->calls),
+		   ((*fp)->self / total) * 100.0,
+		   (*fp)->name);
+	    for (ap = as + narcs - 1; ap >= as; ap--)
+		if ((*ap)->from == *fp) {
+		    printf("    %4ld/%-4ld  %8.2f %8.2f  %6.2f%%  %8.2f %8.2f             %s [%ld]\n",
+			   (*ap)->calls, (*ap)->to->calls,
+			   (*ap)->time, (*ap)->time / ((double) (*ap)->calls),
+			   ((*ap)->time / total) * 100.0,
+			   (*ap)->self, (*ap)->self / ((double) (*ap)->calls),
+			   (*ap)->to->name, (*ap)->to->num);
+		}
+	}
+    }
+    return 0;
+}
+
+/**/
+static int
+zprof_wrapper(Eprog prog, FuncWrap w, char *name)
+{
+    int active = 0;
+    struct sfunc sf, *sp;
+    Pfunc f = NULL;
+    Parc a = NULL;
+    struct timeval tv;
+    struct timezone dummy;
+    double prev = 0, now;
+
+    if (zprof_module && !(zprof_module->flags & MOD_UNLOAD)) {
+        active = 1;
+        if (!(f = findpfunc(name))) {
+            f = (Pfunc) zalloc(sizeof(*f));
+            f->name = ztrdup(name);
+            f->calls = 0;
+            f->time = f->self = 0.0;
+            f->next = calls;
+            calls = f;
+            ncalls++;
+        }
+        if (stack) {
+            if (!(a = findparc(stack->p, f))) {
+                a = (Parc) zalloc(sizeof(*a));
+                a->from = stack->p;
+                a->to = f;
+                a->calls = 0;
+                a->time = a->self = 0.0;
+                a->next = arcs;
+                arcs = a;
+                narcs++;
+            }
+        }
+        sf.prev = stack;
+        sf.p = f;
+        stack = &sf;
+
+        f->calls++;
+        tv.tv_sec = tv.tv_usec = 0;
+        gettimeofday(&tv, &dummy);
+        sf.beg = prev = ((((double) tv.tv_sec) * 1000.0) +
+                         (((double) tv.tv_usec) / 1000.0));
+    }
+    runshfunc(prog, w, name);
+    if (active) {
+        if (zprof_module && !(zprof_module->flags & MOD_UNLOAD)) {
+            tv.tv_sec = tv.tv_usec = 0;
+            gettimeofday(&tv, &dummy);
+
+            now = ((((double) tv.tv_sec) * 1000.0) +
+                   (((double) tv.tv_usec) / 1000.0));
+            f->self += now - sf.beg;
+            for (sp = sf.prev; sp && sp->p != f; sp = sp->prev);
+            if (!sp)
+                f->time += now - prev;
+            if (a) {
+                a->calls++;
+                a->self += now - sf.beg;
+            }
+            stack = sf.prev;
+
+            if (stack) {
+                stack->beg += now - prev;
+                if (a)
+                    a->time += now - prev;
+            }
+        } else
+            stack = sf.prev;
+    }
+    return 0;
+}
+
+static struct builtin bintab[] = {
+    BUILTIN("zprof", 0, bin_zprof, 0, 0, 0, "c", NULL),
+};
+
+static struct funcwrap wrapper[] = {
+    WRAPDEF(zprof_wrapper),
+};
+
+/**/
+int
+setup_(Module m)
+{
+    zprof_module = m;
+    return 0;
+}
+
+/**/
+int
+boot_(Module m)
+{
+    calls = NULL;
+    ncalls = 0;
+    arcs = NULL;
+    narcs = 0;
+    stack = NULL;
+    return !(addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)) |
+	     !addwrapper(m, wrapper));
+}
+
+/**/
+int
+cleanup_(Module m)
+{
+    freepfuncs(calls);
+    freeparcs(arcs);
+    deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
+    deletewrapper(m, wrapper);
+    return 0;
+}
+
+/**/
+int
+finish_(UNUSED(Module m))
+{
+    return 0;
+}