openenvutils/commandshell/shell/src/modules/zprof.c
changeset 0 2e3d3ce01487
child 4 0fdb7f6b0309
equal deleted inserted replaced
-1:000000000000 0:2e3d3ce01487
       
     1 //
       
     2 // © Portions Copyright (c) Symbian Software Ltd 2007. All rights reserved.
       
     3 //
       
     4 /*
       
     5  * zprof.c - a shell function profiling module for zsh
       
     6  *
       
     7  * This file is part of zsh, the Z shell.
       
     8  *
       
     9  * Copyright (c) 1996-1997 Sven Wischnowsky
       
    10  * All rights reserved.
       
    11  *
       
    12  * Permission is hereby granted, without written agreement and without
       
    13  * license or royalty fees, to use, copy, modify, and distribute this
       
    14  * software and to distribute modified versions of this software for any
       
    15  * purpose, provided that the above copyright notice and the following
       
    16  * two paragraphs appear in all copies of this software.
       
    17  *
       
    18  * In no event shall Sven Wischnowsky or the Zsh Development Group be liable
       
    19  * to any party for direct, indirect, special, incidental, or consequential
       
    20  * damages arising out of the use of this software and its documentation,
       
    21  * even if Sven Wischnowsky and the Zsh Development Group have been advised of
       
    22  * the possibility of such damage.
       
    23  *
       
    24  * Sven Wischnowsky and the Zsh Development Group specifically disclaim any
       
    25  * warranties, including, but not limited to, the implied warranties of
       
    26  * merchantability and fitness for a particular purpose.  The software
       
    27  * provided hereunder is on an "as is" basis, and Sven Wischnowsky and the
       
    28  * Zsh Development Group have no obligation to provide maintenance,
       
    29  * support, updates, enhancements, or modifications.
       
    30  *
       
    31  */
       
    32 #include "zprof.mdh"
       
    33 #include "zprof.pro"
       
    34 
       
    35 #include <sys/time.h>
       
    36 #include <unistd.h>
       
    37 
       
    38 #ifdef __SYMBIAN32__
       
    39 #ifdef __WINSCW__
       
    40 #pragma warn_unusedarg off
       
    41 #pragma warn_possunwant off
       
    42 #endif//__WINSCW__
       
    43 #endif//__SYMBIAN32__
       
    44 
       
    45 typedef struct pfunc *Pfunc;
       
    46 
       
    47 struct pfunc {
       
    48     Pfunc next;
       
    49     char *name;
       
    50     long calls;
       
    51     double time;
       
    52     double self;
       
    53     long num;
       
    54 };
       
    55 
       
    56 typedef struct sfunc *Sfunc;
       
    57 
       
    58 struct sfunc {
       
    59     Pfunc p;
       
    60     Sfunc prev;
       
    61     double beg;
       
    62 };
       
    63 
       
    64 typedef struct parc *Parc;
       
    65 
       
    66 struct parc {
       
    67     Parc next;
       
    68     Pfunc from;
       
    69     Pfunc to;
       
    70     long calls;
       
    71     double time;
       
    72     double self;
       
    73 };
       
    74 
       
    75 static Pfunc calls;
       
    76 static int ncalls;
       
    77 static Parc arcs;
       
    78 static int narcs;
       
    79 static Sfunc stack;
       
    80 static Module zprof_module;
       
    81 
       
    82 static void
       
    83 freepfuncs(Pfunc f)
       
    84 {
       
    85     Pfunc n;
       
    86 
       
    87     for (; f; f = n) {
       
    88 	n = f->next;
       
    89 	zsfree(f->name);
       
    90 	zfree(f, sizeof(*f));
       
    91     }
       
    92 }
       
    93 
       
    94 static void
       
    95 freeparcs(Parc a)
       
    96 {
       
    97     Parc n;
       
    98 
       
    99     for (; a; a = n) {
       
   100 	n = a->next;
       
   101 	zfree(a, sizeof(*a));
       
   102     }
       
   103 }
       
   104 
       
   105 static Pfunc
       
   106 findpfunc(char *name)
       
   107 {
       
   108     Pfunc f;
       
   109 
       
   110     for (f = calls; f; f = f->next)
       
   111 	if (!strcmp(name, f->name))
       
   112 	    return f;
       
   113 
       
   114     return NULL;
       
   115 }
       
   116 
       
   117 static Parc
       
   118 findparc(Pfunc f, Pfunc t)
       
   119 {
       
   120     Parc a;
       
   121 
       
   122     for (a = arcs; a; a = a->next)
       
   123 	if (a->from == f && a->to == t)
       
   124 	    return a;
       
   125 
       
   126     return NULL;
       
   127 }
       
   128 
       
   129 static int
       
   130 cmpsfuncs(Pfunc *a, Pfunc *b)
       
   131 {
       
   132     return ((*a)->self > (*b)->self ? -1 : ((*a)->self != (*b)->self));
       
   133 }
       
   134 
       
   135 static int
       
   136 cmptfuncs(Pfunc *a, Pfunc *b)
       
   137 {
       
   138     return ((*a)->time > (*b)->time ? -1 : ((*a)->time != (*b)->time));
       
   139 }
       
   140 
       
   141 static int
       
   142 cmpparcs(Parc *a, Parc *b)
       
   143 {
       
   144     return ((*a)->time > (*b)->time ? -1 : ((*a)->time != (*b)->time));
       
   145 }
       
   146 
       
   147 static int
       
   148 bin_zprof(UNUSED(char *nam), UNUSED(char **args), Options ops, UNUSED(int func))
       
   149 {
       
   150     if (OPT_ISSET(ops,'c')) {
       
   151 	freepfuncs(calls);
       
   152 	calls = NULL;
       
   153 	ncalls = 0;
       
   154 	freeparcs(arcs);
       
   155 	arcs = NULL;
       
   156 	narcs = 0;
       
   157     } else {
       
   158 	VARARR(Pfunc, fs, (ncalls + 1));
       
   159 	Pfunc f, *fp;
       
   160 	VARARR(Parc, as, (narcs + 1));
       
   161 	Parc a, *ap;
       
   162 	long i;
       
   163 	double total;
       
   164 
       
   165 	for (total = 0.0, f = calls, fp = fs; f; f = f->next, fp++) {
       
   166 	    *fp = f;
       
   167 	    total += f->self;
       
   168 	}
       
   169 	*fp = NULL;
       
   170 	for (a = arcs, ap = as; a; a = a->next, ap++)
       
   171 	    *ap = a;
       
   172 	*ap = NULL;
       
   173 
       
   174 	qsort(fs, ncalls, sizeof(f),
       
   175 	      (int (*) _((const void *, const void *))) cmpsfuncs);
       
   176 	qsort(as, narcs, sizeof(a),
       
   177 	      (int (*) _((const void *, const void *))) cmpparcs);
       
   178 
       
   179 	printf("num  calls                time                       self            name\n-----------------------------------------------------------------------------------\n");
       
   180 	for (fp = fs, i = 1; *fp; fp++, i++) {
       
   181 	    printf("%2ld) %4ld       %8.2f %8.2f  %6.2f%%  %8.2f %8.2f  %6.2f%%  %s\n",
       
   182 		   ((*fp)->num = i),
       
   183 		   (*fp)->calls,
       
   184 		   (*fp)->time, (*fp)->time / ((double) (*fp)->calls),
       
   185 		   ((*fp)->time / total) * 100.0,
       
   186 		   (*fp)->self, (*fp)->self / ((double) (*fp)->calls),
       
   187 		   ((*fp)->self / total) * 100.0,
       
   188 		   (*fp)->name);
       
   189 	}
       
   190 	qsort(fs, ncalls, sizeof(f),
       
   191 	      (int (*) _((const void *, const void *))) cmptfuncs);
       
   192 
       
   193 	for (fp = fs; *fp; fp++) {
       
   194 	    printf("\n-----------------------------------------------------------------------------------\n\n");
       
   195 	    for (ap = as; *ap; ap++)
       
   196 		if ((*ap)->to == *fp) {
       
   197 		    printf("    %4ld/%-4ld  %8.2f %8.2f  %6.2f%%  %8.2f %8.2f             %s [%ld]\n",
       
   198 			   (*ap)->calls, (*fp)->calls,
       
   199 			   (*ap)->time, (*ap)->time / ((double) (*ap)->calls),
       
   200 			   ((*ap)->time / total) * 100.0,
       
   201 			   (*ap)->self, (*ap)->self / ((double) (*ap)->calls),
       
   202 			   (*ap)->from->name, (*ap)->from->num);
       
   203 		}
       
   204 	    printf("%2ld) %4ld       %8.2f %8.2f  %6.2f%%  %8.2f %8.2f  %6.2f%%  %s\n",
       
   205 		   (*fp)->num, (*fp)->calls,
       
   206 		   (*fp)->time, (*fp)->time / ((double) (*fp)->calls),
       
   207 		   ((*fp)->time / total) * 100.0,
       
   208 		   (*fp)->self, (*fp)->self / ((double) (*fp)->calls),
       
   209 		   ((*fp)->self / total) * 100.0,
       
   210 		   (*fp)->name);
       
   211 	    for (ap = as + narcs - 1; ap >= as; ap--)
       
   212 		if ((*ap)->from == *fp) {
       
   213 		    printf("    %4ld/%-4ld  %8.2f %8.2f  %6.2f%%  %8.2f %8.2f             %s [%ld]\n",
       
   214 			   (*ap)->calls, (*ap)->to->calls,
       
   215 			   (*ap)->time, (*ap)->time / ((double) (*ap)->calls),
       
   216 			   ((*ap)->time / total) * 100.0,
       
   217 			   (*ap)->self, (*ap)->self / ((double) (*ap)->calls),
       
   218 			   (*ap)->to->name, (*ap)->to->num);
       
   219 		}
       
   220 	}
       
   221     }
       
   222     return 0;
       
   223 }
       
   224 
       
   225 /**/
       
   226 static int
       
   227 zprof_wrapper(Eprog prog, FuncWrap w, char *name)
       
   228 {
       
   229     int active = 0;
       
   230     struct sfunc sf, *sp;
       
   231     Pfunc f = NULL;
       
   232     Parc a = NULL;
       
   233     struct timeval tv;
       
   234     struct timezone dummy;
       
   235     double prev = 0, now;
       
   236 
       
   237     if (zprof_module && !(zprof_module->flags & MOD_UNLOAD)) {
       
   238         active = 1;
       
   239         if (!(f = findpfunc(name))) {
       
   240             f = (Pfunc) zalloc(sizeof(*f));
       
   241             f->name = ztrdup(name);
       
   242             f->calls = 0;
       
   243             f->time = f->self = 0.0;
       
   244             f->next = calls;
       
   245             calls = f;
       
   246             ncalls++;
       
   247         }
       
   248         if (stack) {
       
   249             if (!(a = findparc(stack->p, f))) {
       
   250                 a = (Parc) zalloc(sizeof(*a));
       
   251                 a->from = stack->p;
       
   252                 a->to = f;
       
   253                 a->calls = 0;
       
   254                 a->time = a->self = 0.0;
       
   255                 a->next = arcs;
       
   256                 arcs = a;
       
   257                 narcs++;
       
   258             }
       
   259         }
       
   260         sf.prev = stack;
       
   261         sf.p = f;
       
   262         stack = &sf;
       
   263 
       
   264         f->calls++;
       
   265         tv.tv_sec = tv.tv_usec = 0;
       
   266         gettimeofday(&tv, &dummy);
       
   267         sf.beg = prev = ((((double) tv.tv_sec) * 1000.0) +
       
   268                          (((double) tv.tv_usec) / 1000.0));
       
   269     }
       
   270     runshfunc(prog, w, name);
       
   271     if (active) {
       
   272         if (zprof_module && !(zprof_module->flags & MOD_UNLOAD)) {
       
   273             tv.tv_sec = tv.tv_usec = 0;
       
   274             gettimeofday(&tv, &dummy);
       
   275 
       
   276             now = ((((double) tv.tv_sec) * 1000.0) +
       
   277                    (((double) tv.tv_usec) / 1000.0));
       
   278             f->self += now - sf.beg;
       
   279             for (sp = sf.prev; sp && sp->p != f; sp = sp->prev);
       
   280             if (!sp)
       
   281                 f->time += now - prev;
       
   282             if (a) {
       
   283                 a->calls++;
       
   284                 a->self += now - sf.beg;
       
   285             }
       
   286             stack = sf.prev;
       
   287 
       
   288             if (stack) {
       
   289                 stack->beg += now - prev;
       
   290                 if (a)
       
   291                     a->time += now - prev;
       
   292             }
       
   293         } else
       
   294             stack = sf.prev;
       
   295     }
       
   296     return 0;
       
   297 }
       
   298 
       
   299 static struct builtin bintab[] = {
       
   300     BUILTIN("zprof", 0, bin_zprof, 0, 0, 0, "c", NULL),
       
   301 };
       
   302 
       
   303 static struct funcwrap wrapper[] = {
       
   304     WRAPDEF(zprof_wrapper),
       
   305 };
       
   306 
       
   307 /**/
       
   308 int
       
   309 setup_(Module m)
       
   310 {
       
   311     zprof_module = m;
       
   312     return 0;
       
   313 }
       
   314 
       
   315 /**/
       
   316 int
       
   317 boot_(Module m)
       
   318 {
       
   319     calls = NULL;
       
   320     ncalls = 0;
       
   321     arcs = NULL;
       
   322     narcs = 0;
       
   323     stack = NULL;
       
   324     return !(addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)) |
       
   325 	     !addwrapper(m, wrapper));
       
   326 }
       
   327 
       
   328 /**/
       
   329 int
       
   330 cleanup_(Module m)
       
   331 {
       
   332     freepfuncs(calls);
       
   333     freeparcs(arcs);
       
   334     deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
       
   335     deletewrapper(m, wrapper);
       
   336     return 0;
       
   337 }
       
   338 
       
   339 /**/
       
   340 int
       
   341 finish_(UNUSED(Module m))
       
   342 {
       
   343     return 0;
       
   344 }