nmeter: stop using data/bss; reduce amount of reads from /proc
# size */*/nmeter.o text data bss dec hex filename 4366 80 16 4462 116e busybox.t0/miscutils/nmeter.o 4386 0 0 4386 1122 busybox.t2/miscutils/nmeter.o
This commit is contained in:
parent
0b3b41b62a
commit
199c0d542b
@ -17,33 +17,67 @@
|
|||||||
|
|
||||||
typedef unsigned long long ullong;
|
typedef unsigned long long ullong;
|
||||||
|
|
||||||
enum { proc_file_size = 4096 };
|
enum { PROC_FILE_SIZE = 4096 };
|
||||||
|
|
||||||
typedef struct proc_file {
|
typedef struct proc_file {
|
||||||
const char *name;
|
|
||||||
int gen;
|
|
||||||
char *file;
|
char *file;
|
||||||
|
//const char *name;
|
||||||
|
smallint last_gen;
|
||||||
} proc_file;
|
} proc_file;
|
||||||
|
|
||||||
static proc_file proc_stat = { "/proc/stat", -1 };
|
static const char *const proc_name[] = {
|
||||||
static proc_file proc_loadavg = { "/proc/loadavg", -1 };
|
"stat", // Must match the order of proc_file's!
|
||||||
static proc_file proc_net_dev = { "/proc/net/dev", -1 };
|
"loadavg",
|
||||||
static proc_file proc_meminfo = { "/proc/meminfo", -1 };
|
"net/dev",
|
||||||
static proc_file proc_diskstats = { "/proc/diskstats", -1 };
|
"meminfo",
|
||||||
// Sample #
|
"diskstats",
|
||||||
static int gen = -1;
|
"sys/fs/file-nr",
|
||||||
// Linux 2.6? (otherwise assumes 2.4)
|
};
|
||||||
static int is26 = 0;
|
|
||||||
static struct timeval tv;
|
struct globals {
|
||||||
static int delta = 1000000;
|
// Sample generation flip-flop
|
||||||
static int deltanz = 1000000;
|
smallint gen;
|
||||||
static int need_seconds = 0;
|
// Linux 2.6? (otherwise assumes 2.4)
|
||||||
static const char *final_str = "\n";
|
smallint is26;
|
||||||
|
// 1 if sample delay is not an integer fraction of a second
|
||||||
|
smallint need_seconds;
|
||||||
|
char *cur_outbuf;
|
||||||
|
const char *final_str;
|
||||||
|
int delta;
|
||||||
|
int deltanz;
|
||||||
|
struct timeval tv;
|
||||||
|
#define first_proc_file proc_stat
|
||||||
|
proc_file proc_stat; // Must match the order of proc_name's!
|
||||||
|
proc_file proc_loadavg;
|
||||||
|
proc_file proc_net_dev;
|
||||||
|
proc_file proc_meminfo;
|
||||||
|
proc_file proc_diskstats;
|
||||||
|
proc_file proc_sys_fs_filenr;
|
||||||
|
};
|
||||||
|
#define G (*ptr_to_globals)
|
||||||
|
#define gen (G.gen )
|
||||||
|
#define is26 (G.is26 )
|
||||||
|
#define need_seconds (G.need_seconds )
|
||||||
|
#define cur_outbuf (G.cur_outbuf )
|
||||||
|
#define final_str (G.final_str )
|
||||||
|
#define delta (G.delta )
|
||||||
|
#define deltanz (G.deltanz )
|
||||||
|
#define tv (G.tv )
|
||||||
|
#define proc_stat (G.proc_stat )
|
||||||
|
#define proc_loadavg (G.proc_loadavg )
|
||||||
|
#define proc_net_dev (G.proc_net_dev )
|
||||||
|
#define proc_meminfo (G.proc_meminfo )
|
||||||
|
#define proc_diskstats (G.proc_diskstats )
|
||||||
|
#define proc_sys_fs_filenr (G.proc_sys_fs_filenr)
|
||||||
|
|
||||||
// We depend on this being a char[], not char* - we take sizeof() of it
|
// We depend on this being a char[], not char* - we take sizeof() of it
|
||||||
#define outbuf bb_common_bufsiz1
|
#define outbuf bb_common_bufsiz1
|
||||||
static char *cur_outbuf = outbuf;
|
|
||||||
|
|
||||||
|
#define INIT_G() do { \
|
||||||
|
cur_outbuf = outbuf; \
|
||||||
|
final_str = "\n"; \
|
||||||
|
deltanz = delta = 1000000; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
static inline void reset_outbuf(void)
|
static inline void reset_outbuf(void)
|
||||||
{
|
{
|
||||||
@ -85,27 +119,31 @@ static void put_question_marks(int count)
|
|||||||
put_c('?');
|
put_c('?');
|
||||||
}
|
}
|
||||||
|
|
||||||
static int readfile_z(char *buf, int sz, const char* fname)
|
static void readfile_z(char *buf, int sz, const char* fname)
|
||||||
{
|
{
|
||||||
sz = open_read_close(fname, buf, sz-1);
|
// open_read_close() will do two reads in order to be sure we are at EOF,
|
||||||
if (sz < 0) {
|
// and we don't need/want that.
|
||||||
buf[0] = '\0';
|
// sz = open_read_close(fname, buf, sz-1);
|
||||||
return 1;
|
|
||||||
|
int fd = xopen(fname, O_RDONLY);
|
||||||
|
buf[0] = '\0';
|
||||||
|
if (fd >= 0) {
|
||||||
|
sz = read(fd, buf, sz-1);
|
||||||
|
if (sz > 0) buf[sz] = '\0';
|
||||||
|
close(fd);
|
||||||
}
|
}
|
||||||
buf[sz] = '\0';
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* get_file(proc_file *pf)
|
static const char* get_file(proc_file *pf)
|
||||||
{
|
{
|
||||||
if (pf->gen != gen) {
|
if (pf->last_gen != gen) {
|
||||||
pf->gen = gen;
|
pf->last_gen = gen;
|
||||||
// We allocate proc_file_size bytes. This wastes memory,
|
// We allocate PROC_FILE_SIZE bytes. This wastes memory,
|
||||||
// but allows us to allocate only once (at first sample)
|
// but allows us to allocate only once (at first sample)
|
||||||
// per proc file, and reuse buffer for each sample
|
// per proc file, and reuse buffer for each sample
|
||||||
if (!pf->file)
|
if (!pf->file)
|
||||||
pf->file = xmalloc(proc_file_size);
|
pf->file = xmalloc(PROC_FILE_SIZE);
|
||||||
readfile_z(pf->file, proc_file_size, pf->name);
|
readfile_z(pf->file, PROC_FILE_SIZE, proc_name[pf - &first_proc_file]);
|
||||||
}
|
}
|
||||||
return pf->file;
|
return pf->file;
|
||||||
}
|
}
|
||||||
@ -242,10 +280,10 @@ static s_stat* init_literal(void)
|
|||||||
|
|
||||||
static s_stat* init_delay(const char *param)
|
static s_stat* init_delay(const char *param)
|
||||||
{
|
{
|
||||||
delta = strtol(param, NULL, 0)*1000;
|
delta = bb_strtoi(param, NULL, 0) * 1000;
|
||||||
deltanz = delta > 0 ? delta : 1;
|
deltanz = delta > 0 ? delta : 1;
|
||||||
need_seconds = (1000000%deltanz) != 0;
|
need_seconds = (1000000%deltanz) != 0;
|
||||||
return (s_stat*)0;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static s_stat* init_cr(const char *param)
|
static s_stat* init_cr(const char *param)
|
||||||
@ -281,7 +319,7 @@ static void collect_cpu(cpu_stat *s)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i=0; i<CPU_FIELDCNT; i++) {
|
for (i = 0; i < CPU_FIELDCNT; i++) {
|
||||||
ullong old = s->old[i];
|
ullong old = s->old[i];
|
||||||
if (data[i] < old) old = data[i]; //sanitize
|
if (data[i] < old) old = data[i]; //sanitize
|
||||||
s->old[i] = data[i];
|
s->old[i] = data[i];
|
||||||
@ -289,7 +327,7 @@ static void collect_cpu(cpu_stat *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (all) {
|
if (all) {
|
||||||
for (i=0; i<CPU_FIELDCNT; i++) {
|
for (i = 0; i < CPU_FIELDCNT; i++) {
|
||||||
ullong t = bar_sz * data[i];
|
ullong t = bar_sz * data[i];
|
||||||
norm_all += data[i] = t / all;
|
norm_all += data[i] = t / all;
|
||||||
frac[i] = t % all;
|
frac[i] = t % all;
|
||||||
@ -298,7 +336,7 @@ static void collect_cpu(cpu_stat *s)
|
|||||||
while (norm_all < bar_sz) {
|
while (norm_all < bar_sz) {
|
||||||
unsigned max = frac[0];
|
unsigned max = frac[0];
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
for (i=1; i<CPU_FIELDCNT; i++) {
|
for (i = 1; i < CPU_FIELDCNT; i++) {
|
||||||
if (frac[i] > max) max = frac[i], pos = i;
|
if (frac[i] > max) max = frac[i], pos = i;
|
||||||
}
|
}
|
||||||
frac[pos] = 0; //avoid bumping up same value twice
|
frac[pos] = 0; //avoid bumping up same value twice
|
||||||
@ -640,11 +678,9 @@ S_STAT_END(fd_stat)
|
|||||||
|
|
||||||
static void collect_fd(fd_stat *s)
|
static void collect_fd(fd_stat *s)
|
||||||
{
|
{
|
||||||
char file[4096];
|
|
||||||
ullong data[2];
|
ullong data[2];
|
||||||
|
|
||||||
readfile_z(file, sizeof(file), "/proc/sys/fs/file-nr");
|
if (rdval(get_file(&proc_sys_fs_filenr), "", data, 1, 2)) {
|
||||||
if (rdval(file, "", data, 1, 2)) {
|
|
||||||
put_question_marks(4);
|
put_question_marks(4);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -702,7 +738,7 @@ static s_stat* init_time(const char *param)
|
|||||||
|
|
||||||
static void collect_info(s_stat *s)
|
static void collect_info(s_stat *s)
|
||||||
{
|
{
|
||||||
gen++;
|
gen ^= 1;
|
||||||
while (s) {
|
while (s) {
|
||||||
put(s->label);
|
put(s->label);
|
||||||
s->collect(s);
|
s->collect(s);
|
||||||
@ -714,7 +750,7 @@ static void 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[] = "ncmsfixptbdr";
|
static const char options[] = "ncmsfixptbdr";
|
||||||
static init_func* init_functions[] = {
|
static init_func *const init_functions[] = {
|
||||||
init_if,
|
init_if,
|
||||||
init_cpu,
|
init_cpu,
|
||||||
init_mem,
|
init_mem,
|
||||||
@ -738,10 +774,15 @@ int nmeter_main(int argc, char **argv)
|
|||||||
s_stat *s;
|
s_stat *s;
|
||||||
char *cur, *prev;
|
char *cur, *prev;
|
||||||
|
|
||||||
|
PTR_TO_GLOBALS = xzalloc(sizeof(G));
|
||||||
|
INIT_G();
|
||||||
|
|
||||||
|
xchdir("/proc");
|
||||||
|
|
||||||
if (argc != 2)
|
if (argc != 2)
|
||||||
bb_show_usage();
|
bb_show_usage();
|
||||||
|
|
||||||
if (open_read_close("/proc/version", buf, sizeof(buf)) > 0)
|
if (open_read_close("version", buf, sizeof(buf)) > 0)
|
||||||
is26 = (strstr(buf, " 2.4.")==NULL);
|
is26 = (strstr(buf, " 2.4.")==NULL);
|
||||||
|
|
||||||
// Can use argv[1] directly, but this will mess up
|
// Can use argv[1] directly, but this will mess up
|
||||||
@ -750,11 +791,11 @@ int nmeter_main(int argc, char **argv)
|
|||||||
while (1) {
|
while (1) {
|
||||||
char *param, *p;
|
char *param, *p;
|
||||||
prev = cur;
|
prev = cur;
|
||||||
again:
|
again:
|
||||||
cur = strchr(cur, '%');
|
cur = strchr(cur, '%');
|
||||||
if (!cur)
|
if (!cur)
|
||||||
break;
|
break;
|
||||||
if (cur[1]=='%') { // %%
|
if (cur[1] == '%') { // %%
|
||||||
strcpy(cur, cur+1);
|
strcpy(cur, cur+1);
|
||||||
cur++;
|
cur++;
|
||||||
goto again;
|
goto again;
|
||||||
@ -813,12 +854,12 @@ again:
|
|||||||
collect_info(first);
|
collect_info(first);
|
||||||
reset_outbuf();
|
reset_outbuf();
|
||||||
if (delta >= 0) {
|
if (delta >= 0) {
|
||||||
gettimeofday(&tv, 0);
|
gettimeofday(&tv, NULL);
|
||||||
usleep(delta > 1000000 ? 1000000 : delta - tv.tv_usec%deltanz);
|
usleep(delta > 1000000 ? 1000000 : delta - tv.tv_usec%deltanz);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
gettimeofday(&tv, 0);
|
gettimeofday(&tv, NULL);
|
||||||
collect_info(first);
|
collect_info(first);
|
||||||
put(final_str);
|
put(final_str);
|
||||||
print_outbuf();
|
print_outbuf();
|
||||||
@ -831,9 +872,9 @@ again:
|
|||||||
if (delta >= 0) {
|
if (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, 0);
|
gettimeofday(&tv, NULL);
|
||||||
if (need_seconds)
|
if (need_seconds)
|
||||||
rem = delta - ((ullong)tv.tv_sec*1000000+tv.tv_usec)%deltanz;
|
rem = delta - ((ullong)tv.tv_sec*1000000 + tv.tv_usec) % deltanz;
|
||||||
else
|
else
|
||||||
rem = delta - tv.tv_usec%deltanz;
|
rem = delta - tv.tv_usec%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
|
||||||
@ -845,5 +886,5 @@ again:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
/*return 0;*/
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user