184 lines
4.2 KiB
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(¤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("<idle>");
|
|
current = idle;
|
|
}
|
|
}
|