nmeter: add %T (zero-based timestamp) format

function                                             old     new   delta
collect_tv                                             -     132    +132
collect_monotonic                                      -      61     +61
nmeter_main                                          754     778     +24
gmtime                                                 -      21     +21
init_monotonic                                         -      18     +18
init_functions                                        44      48      +4
packed_usage                                       33432   33420     -12
collect_time                                         125      19    -106
------------------------------------------------------------------------------
(add/remove: 5/0 grow/shrink: 2/2 up/down: 260/-118)          Total: 142 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2020-06-10 15:37:39 +02:00
parent 505eeae402
commit 4789c7cd81

View File

@ -37,6 +37,7 @@
//usage: "\n %[pn] # of processes" //usage: "\n %[pn] # of processes"
//usage: "\n %b Block io" //usage: "\n %b Block io"
//usage: "\n %Nt Time (with N decimal points)" //usage: "\n %Nt Time (with N decimal points)"
//usage: "\n %NT Zero-based timestamp (with N decimal points)"
//usage: "\n %r Print <cr> instead of <lf> at EOL" //usage: "\n %r Print <cr> instead of <lf> at EOL"
//TODO: //TODO:
@ -88,6 +89,7 @@ struct globals {
int delta; int delta;
unsigned deltanz; unsigned deltanz;
struct timeval tv; struct timeval tv;
struct timeval start;
#define first_proc_file proc_stat #define first_proc_file proc_stat
proc_file proc_stat; // Must match the order of proc_name's! proc_file proc_stat; // Must match the order of proc_name's!
proc_file proc_loadavg; proc_file proc_loadavg;
@ -101,7 +103,6 @@ struct globals {
#define is26 (G.is26 ) #define is26 (G.is26 )
#define need_seconds (G.need_seconds ) #define need_seconds (G.need_seconds )
#define cur_outbuf (G.cur_outbuf ) #define cur_outbuf (G.cur_outbuf )
#define tv (G.tv )
#define proc_stat (G.proc_stat ) #define proc_stat (G.proc_stat )
#define proc_loadavg (G.proc_loadavg ) #define proc_loadavg (G.proc_loadavg )
#define proc_net_dev (G.proc_net_dev ) #define proc_net_dev (G.proc_net_dev )
@ -754,25 +755,53 @@ S_STAT(time_stat)
unsigned scale; unsigned scale;
S_STAT_END(time_stat) S_STAT_END(time_stat)
static void FAST_FUNC collect_time(time_stat *s) static void FAST_FUNC collect_tv(time_stat *s, struct timeval *tv, int local)
{ {
char buf[sizeof("12:34:56.123456")]; char buf[sizeof("12:34:56.123456")];
struct tm* tm; struct tm* tm;
unsigned us = tv.tv_usec + s->scale/2; unsigned us = tv->tv_usec + s->scale/2;
time_t t = tv.tv_sec; time_t t = tv->tv_sec;
if (us >= 1000000) { if (us >= 1000000) {
t++; t++;
us -= 1000000; us -= 1000000;
} }
tm = localtime(&t); if (local)
tm = localtime(&t);
else
tm = gmtime(&t);
sprintf(buf, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec); sprintf(buf, "%02u:%02u:%02u", tm->tm_hour, tm->tm_min, tm->tm_sec);
if (s->prec) if (s->prec)
sprintf(buf+8, ".%0*d", s->prec, us / s->scale); sprintf(buf+8, ".%0*u", s->prec, us / s->scale);
put(buf); put(buf);
} }
static void FAST_FUNC collect_time(time_stat *s)
{
collect_tv(s, &G.tv, /*local:*/ 1);
}
static void FAST_FUNC collect_monotonic(time_stat *s)
{
struct timeval tv_mono;
tv_mono.tv_sec = G.tv.tv_sec - G.start.tv_sec;
#if 0 /* Do we want this? */
if (tv_mono.tv_sec < 0) {
/* Time went backwards, reset start time to "now" */
tv_mono.tv_sec = 0;
G.start = G.tv;
}
#endif
tv_mono.tv_usec = G.tv.tv_usec - G.start.tv_usec;
if ((int32_t)tv_mono.tv_usec < 0) {
tv_mono.tv_usec += 1000000;
tv_mono.tv_sec--;
}
collect_tv(s, &tv_mono, /*local:*/ 0);
}
static s_stat* init_time(const char *param) static s_stat* init_time(const char *param)
{ {
int prec; int prec;
@ -789,6 +818,13 @@ static s_stat* init_time(const char *param)
return (s_stat*)s; return (s_stat*)s;
} }
static s_stat* init_monotonic(const char *param)
{
time_stat *s = (void*)init_time(param);
s->collect = collect_monotonic;
return (s_stat*)s;
}
static void FAST_FUNC collect_info(s_stat *s) static void FAST_FUNC collect_info(s_stat *s)
{ {
gen ^= 1; gen ^= 1;
@ -801,7 +837,7 @@ static void FAST_FUNC collect_info(s_stat *s)
typedef s_stat* init_func(const char *param); typedef s_stat* init_func(const char *param);
static const char options[] ALIGN1 = "ncmsfixptbr"; static const char options[] ALIGN1 = "ncmsfixptTbr";
static init_func *const init_functions[] = { static init_func *const init_functions[] = {
init_if, init_if,
init_cpu, init_cpu,
@ -812,6 +848,7 @@ static init_func *const init_functions[] = {
init_ctx, init_ctx,
init_fork, init_fork,
init_time, init_time,
init_monotonic,
init_blk, init_blk,
init_cr init_cr
}; };
@ -913,13 +950,15 @@ int nmeter_main(int argc UNUSED_PARAM, char **argv)
// Generate first samples but do not print them, they're bogus // Generate first samples but do not print them, they're bogus
collect_info(first); collect_info(first);
reset_outbuf(); reset_outbuf();
if (G.delta >= 0) { if (G.delta >= 0) {
gettimeofday(&tv, NULL); gettimeofday(&G.tv, NULL);
usleep(G.delta > 1000000 ? 1000000 : G.delta - tv.tv_usec % G.deltanz); usleep(G.delta > 1000000 ? 1000000 : G.delta - G.tv.tv_usec % G.deltanz);
} }
gettimeofday(&G.start, NULL);
G.tv = G.start;
while (1) { while (1) {
gettimeofday(&tv, NULL);
collect_info(first); collect_info(first);
put_c(G.final_char); put_c(G.final_char);
print_outbuf(); print_outbuf();
@ -932,11 +971,11 @@ int nmeter_main(int argc UNUSED_PARAM, char **argv)
if (G.delta >= 0) { if (G.delta >= 0) {
int rem; int rem;
// can be commented out, will sacrifice sleep time precision a bit // can be commented out, will sacrifice sleep time precision a bit
gettimeofday(&tv, NULL); gettimeofday(&G.tv, NULL);
if (need_seconds) if (need_seconds)
rem = G.delta - ((ullong)tv.tv_sec*1000000 + tv.tv_usec) % G.deltanz; rem = G.delta - ((ullong)G.tv.tv_sec*1000000 + G.tv.tv_usec) % G.deltanz;
else else
rem = G.delta - (unsigned)tv.tv_usec % G.deltanz; rem = G.delta - (unsigned)G.tv.tv_usec % G.deltanz;
// Sometimes kernel wakes us up just a tiny bit earlier than asked // Sometimes kernel wakes us up just a tiny bit earlier than asked
// Do not go to very short sleep in this case // Do not go to very short sleep in this case
if (rem < (unsigned)G.delta / 128) { if (rem < (unsigned)G.delta / 128) {
@ -944,6 +983,7 @@ int nmeter_main(int argc UNUSED_PARAM, char **argv)
} }
usleep(rem); usleep(rem);
} }
gettimeofday(&G.tv, NULL);
} }
/*return 0;*/ /*return 0;*/