Files
sics/statistics.c

184 lines
4.2 KiB
C

#include <sics.h>
#include <sys/time.h>
#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(&current->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(&current->tim, timeDif(last, now));
last = now;
if (current != NULL) {
if (current->last.tv_sec >= 0) {
timeAdd(&current->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("<idle>");
current = idle;
}
}