#include #include #include "statistics.h" typedef struct timeval tv_t; struct Statistics { tv_t tim; tv_t last; tv_t total; long cnt; char *name; Statistics *next; }; static Statistics *current = NULL; static tv_t last, lastStat; static Statistics *idle = NULL, *list = NULL; static int init = 1; /*-----------------------------------------------------------------------*/ tv_t timeDif(tv_t t1, tv_t t2) { tv_t result; result.tv_usec = t2.tv_usec - t1.tv_usec; result.tv_sec = t2.tv_sec - t1.tv_sec; if (result.tv_usec < 0) { result.tv_usec += 1000000; result.tv_sec--; } if (result.tv_sec < 0) { result.tv_sec += 24 * 3600; } return result; } /*-----------------------------------------------------------------------*/ void timeAdd(tv_t * t1, tv_t t2) { t1->tv_usec += t2.tv_usec; t1->tv_sec += t2.tv_sec + (t1->tv_usec / 1000000); t1->tv_usec %= 1000000; } /*-----------------------------------------------------------------------*/ double timeFloat(tv_t t) { return t.tv_sec + 1e-6 * t.tv_usec; } /*-----------------------------------------------------------------------*/ int StatisticsCommand(SConnection * con, SicsInterp * pSics, void *pData, int argc, char *argv[]) { Statistics *p; tv_t now; double dif, percent, full, dt, calls; gettimeofday(&now, 0); dif = timeFloat(timeDif(lastStat, now)); SCPrintf(con, eLog, "calls/s time[%%] full[%%] mean[ms] command"); SCPrintf(con, eLog, "----------------------------------------------"); for (p = list; p != NULL; p = p->next) { if (dif > 0) { calls = p->cnt / dif; percent = timeFloat(p->tim) * 100 / dif; full = timeFloat(p->total) * 100 / dif; if (full > 0 || percent > 0) { if (p->cnt > 0) { dt = timeFloat(p->total) * 1000.0 / p->cnt; } else { dt = 0; } SCPrintf(con, eLog, "%7.1f %7.1f %7.1f %8.2f %s", calls, percent, full, dt, p->name); } } p->cnt = 0; p->tim.tv_sec = 0; p->tim.tv_usec = 0; p->total.tv_sec = 0; p->total.tv_usec = 0; } SCPrintf(con, eLog, "----------------------------------------------"); SCPrintf(con, eLog, "total time %.2f", dif); lastStat = now; return 1; } /*-----------------------------------------------------------------------*/ Statistics *StatisticsNew(char *name) { Statistics *new; if (init) { gettimeofday(&lastStat, 0); last = lastStat; init = 0; } new = calloc(1, sizeof(*new)); if (new) { new->cnt = 0; new->tim.tv_sec = 0; new->tim.tv_usec = 0; new->total.tv_sec = 0; new->total.tv_usec = 0; new->last.tv_sec = -1; new->next = list; new->name = strdup(name); list = new; } return new; } /*-----------------------------------------------------------------------*/ void StatisticsKill(Statistics * stat) { Statistics *p, **last; /* find in list */ last = &list; for (p = list; p != NULL && p != stat; p = p->next) { last = &p->next; } /* remove from list */ if (p == stat) { *last = p->next; } /* kill it */ if (stat->name) { free(stat->name); stat->name = NULL; } free(stat); } /*-----------------------------------------------------------------------*/ Statistics *StatisticsBegin(Statistics * stat) { Statistics *res; tv_t now; res = current; gettimeofday(&now, 0); if (current != NULL) { timeAdd(¤t->tim, timeDif(last, now)); } last = now; current = stat; stat->last = now; stat->cnt++; return res; } /*-----------------------------------------------------------------------*/ void StatisticsEnd(Statistics * stat) { tv_t now; gettimeofday(&now, 0); timeAdd(¤t->tim, timeDif(last, now)); last = now; if (current != NULL) { if (current->last.tv_sec >= 0) { timeAdd(¤t->total, timeDif(current->last, now)); } current->last.tv_sec = -1; } current = stat; } /*-----------------------------------------------------------------------*/ void StatisticsInit(void) { if (idle == NULL) { AddCmd("statistics", StatisticsCommand); last = lastStat; idle = StatisticsNew(""); current = idle; } }