aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-05-30 14:48:38 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-05-30 14:48:38 +0000
commit199c0d542b51b55b99dddc1742c23325288f79eb (patch)
treee96bc50264dc59c14d0a32aa4d84384439dd4586
parent0b3b41b62acd6c2911ea4f08e0dd96f93334aff5 (diff)
downloadbusybox-w32-199c0d542b51b55b99dddc1742c23325288f79eb.tar.gz
busybox-w32-199c0d542b51b55b99dddc1742c23325288f79eb.tar.bz2
busybox-w32-199c0d542b51b55b99dddc1742c23325288f79eb.zip
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
-rw-r--r--miscutils/nmeter.c137
1 files changed, 89 insertions, 48 deletions
diff --git a/miscutils/nmeter.c b/miscutils/nmeter.c
index e15cc8c71..3152b74e3 100644
--- a/miscutils/nmeter.c
+++ b/miscutils/nmeter.c
@@ -17,33 +17,67 @@
17 17
18typedef unsigned long long ullong; 18typedef unsigned long long ullong;
19 19
20enum { proc_file_size = 4096 }; 20enum { PROC_FILE_SIZE = 4096 };
21 21
22typedef struct proc_file { 22typedef struct proc_file {
23 const char *name;
24 int gen;
25 char *file; 23 char *file;
24 //const char *name;
25 smallint last_gen;
26} proc_file; 26} proc_file;
27 27
28static proc_file proc_stat = { "/proc/stat", -1 }; 28static const char *const proc_name[] = {
29static proc_file proc_loadavg = { "/proc/loadavg", -1 }; 29 "stat", // Must match the order of proc_file's!
30static proc_file proc_net_dev = { "/proc/net/dev", -1 }; 30 "loadavg",
31static proc_file proc_meminfo = { "/proc/meminfo", -1 }; 31 "net/dev",
32static proc_file proc_diskstats = { "/proc/diskstats", -1 }; 32 "meminfo",
33// Sample # 33 "diskstats",
34static int gen = -1; 34 "sys/fs/file-nr",
35// Linux 2.6? (otherwise assumes 2.4) 35};
36static int is26 = 0; 36
37static struct timeval tv; 37struct globals {
38static int delta = 1000000; 38 // Sample generation flip-flop
39static int deltanz = 1000000; 39 smallint gen;
40static int need_seconds = 0; 40 // Linux 2.6? (otherwise assumes 2.4)
41static const char *final_str = "\n"; 41 smallint is26;
42 // 1 if sample delay is not an integer fraction of a second
43 smallint need_seconds;
44 char *cur_outbuf;
45 const char *final_str;
46 int delta;
47 int deltanz;
48 struct timeval tv;
49#define first_proc_file proc_stat
50 proc_file proc_stat; // Must match the order of proc_name's!
51 proc_file proc_loadavg;
52 proc_file proc_net_dev;
53 proc_file proc_meminfo;
54 proc_file proc_diskstats;
55 proc_file proc_sys_fs_filenr;
56};
57#define G (*ptr_to_globals)
58#define gen (G.gen )
59#define is26 (G.is26 )
60#define need_seconds (G.need_seconds )
61#define cur_outbuf (G.cur_outbuf )
62#define final_str (G.final_str )
63#define delta (G.delta )
64#define deltanz (G.deltanz )
65#define tv (G.tv )
66#define proc_stat (G.proc_stat )
67#define proc_loadavg (G.proc_loadavg )
68#define proc_net_dev (G.proc_net_dev )
69#define proc_meminfo (G.proc_meminfo )
70#define proc_diskstats (G.proc_diskstats )
71#define proc_sys_fs_filenr (G.proc_sys_fs_filenr)
42 72
43// We depend on this being a char[], not char* - we take sizeof() of it 73// We depend on this being a char[], not char* - we take sizeof() of it
44#define outbuf bb_common_bufsiz1 74#define outbuf bb_common_bufsiz1
45static char *cur_outbuf = outbuf;
46 75
76#define INIT_G() do { \
77 cur_outbuf = outbuf; \
78 final_str = "\n"; \
79 deltanz = delta = 1000000; \
80 } while (0)
47 81
48static inline void reset_outbuf(void) 82static inline void reset_outbuf(void)
49{ 83{
@@ -85,27 +119,31 @@ static void put_question_marks(int count)
85 put_c('?'); 119 put_c('?');
86} 120}
87 121
88static int readfile_z(char *buf, int sz, const char* fname) 122static void readfile_z(char *buf, int sz, const char* fname)
89{ 123{
90 sz = open_read_close(fname, buf, sz-1); 124// open_read_close() will do two reads in order to be sure we are at EOF,
91 if (sz < 0) { 125// and we don't need/want that.
92 buf[0] = '\0'; 126// sz = open_read_close(fname, buf, sz-1);
93 return 1; 127
128 int fd = xopen(fname, O_RDONLY);
129 buf[0] = '\0';
130 if (fd >= 0) {
131 sz = read(fd, buf, sz-1);
132 if (sz > 0) buf[sz] = '\0';
133 close(fd);
94 } 134 }
95 buf[sz] = '\0';
96 return 0;
97} 135}
98 136
99static const char* get_file(proc_file *pf) 137static const char* get_file(proc_file *pf)
100{ 138{
101 if (pf->gen != gen) { 139 if (pf->last_gen != gen) {
102 pf->gen = gen; 140 pf->last_gen = gen;
103 // We allocate proc_file_size bytes. This wastes memory, 141 // We allocate PROC_FILE_SIZE bytes. This wastes memory,
104 // but allows us to allocate only once (at first sample) 142 // but allows us to allocate only once (at first sample)
105 // per proc file, and reuse buffer for each sample 143 // per proc file, and reuse buffer for each sample
106 if (!pf->file) 144 if (!pf->file)
107 pf->file = xmalloc(proc_file_size); 145 pf->file = xmalloc(PROC_FILE_SIZE);
108 readfile_z(pf->file, proc_file_size, pf->name); 146 readfile_z(pf->file, PROC_FILE_SIZE, proc_name[pf - &first_proc_file]);
109 } 147 }
110 return pf->file; 148 return pf->file;
111} 149}
@@ -242,10 +280,10 @@ static s_stat* init_literal(void)
242 280
243static s_stat* init_delay(const char *param) 281static s_stat* init_delay(const char *param)
244{ 282{
245 delta = strtol(param, NULL, 0)*1000; 283 delta = bb_strtoi(param, NULL, 0) * 1000;
246 deltanz = delta > 0 ? delta : 1; 284 deltanz = delta > 0 ? delta : 1;
247 need_seconds = (1000000%deltanz) != 0; 285 need_seconds = (1000000%deltanz) != 0;
248 return (s_stat*)0; 286 return NULL;
249} 287}
250 288
251static s_stat* init_cr(const char *param) 289static s_stat* init_cr(const char *param)
@@ -281,7 +319,7 @@ static void collect_cpu(cpu_stat *s)
281 return; 319 return;
282 } 320 }
283 321
284 for (i=0; i<CPU_FIELDCNT; i++) { 322 for (i = 0; i < CPU_FIELDCNT; i++) {
285 ullong old = s->old[i]; 323 ullong old = s->old[i];
286 if (data[i] < old) old = data[i]; //sanitize 324 if (data[i] < old) old = data[i]; //sanitize
287 s->old[i] = data[i]; 325 s->old[i] = data[i];
@@ -289,7 +327,7 @@ static void collect_cpu(cpu_stat *s)
289 } 327 }
290 328
291 if (all) { 329 if (all) {
292 for (i=0; i<CPU_FIELDCNT; i++) { 330 for (i = 0; i < CPU_FIELDCNT; i++) {
293 ullong t = bar_sz * data[i]; 331 ullong t = bar_sz * data[i];
294 norm_all += data[i] = t / all; 332 norm_all += data[i] = t / all;
295 frac[i] = t % all; 333 frac[i] = t % all;
@@ -298,7 +336,7 @@ static void collect_cpu(cpu_stat *s)
298 while (norm_all < bar_sz) { 336 while (norm_all < bar_sz) {
299 unsigned max = frac[0]; 337 unsigned max = frac[0];
300 int pos = 0; 338 int pos = 0;
301 for (i=1; i<CPU_FIELDCNT; i++) { 339 for (i = 1; i < CPU_FIELDCNT; i++) {
302 if (frac[i] > max) max = frac[i], pos = i; 340 if (frac[i] > max) max = frac[i], pos = i;
303 } 341 }
304 frac[pos] = 0; //avoid bumping up same value twice 342 frac[pos] = 0; //avoid bumping up same value twice
@@ -640,11 +678,9 @@ S_STAT_END(fd_stat)
640 678
641static void collect_fd(fd_stat *s) 679static void collect_fd(fd_stat *s)
642{ 680{
643 char file[4096];
644 ullong data[2]; 681 ullong data[2];
645 682
646 readfile_z(file, sizeof(file), "/proc/sys/fs/file-nr"); 683 if (rdval(get_file(&proc_sys_fs_filenr), "", data, 1, 2)) {
647 if (rdval(file, "", data, 1, 2)) {
648 put_question_marks(4); 684 put_question_marks(4);
649 return; 685 return;
650 } 686 }
@@ -702,7 +738,7 @@ static s_stat* init_time(const char *param)
702 738
703static void collect_info(s_stat *s) 739static void collect_info(s_stat *s)
704{ 740{
705 gen++; 741 gen ^= 1;
706 while (s) { 742 while (s) {
707 put(s->label); 743 put(s->label);
708 s->collect(s); 744 s->collect(s);
@@ -714,7 +750,7 @@ static void collect_info(s_stat *s)
714typedef s_stat* init_func(const char *param); 750typedef s_stat* init_func(const char *param);
715 751
716static const char options[] = "ncmsfixptbdr"; 752static const char options[] = "ncmsfixptbdr";
717static init_func* init_functions[] = { 753static init_func *const init_functions[] = {
718 init_if, 754 init_if,
719 init_cpu, 755 init_cpu,
720 init_mem, 756 init_mem,
@@ -738,10 +774,15 @@ int nmeter_main(int argc, char **argv)
738 s_stat *s; 774 s_stat *s;
739 char *cur, *prev; 775 char *cur, *prev;
740 776
777 PTR_TO_GLOBALS = xzalloc(sizeof(G));
778 INIT_G();
779
780 xchdir("/proc");
781
741 if (argc != 2) 782 if (argc != 2)
742 bb_show_usage(); 783 bb_show_usage();
743 784
744 if (open_read_close("/proc/version", buf, sizeof(buf)) > 0) 785 if (open_read_close("version", buf, sizeof(buf)) > 0)
745 is26 = (strstr(buf, " 2.4.")==NULL); 786 is26 = (strstr(buf, " 2.4.")==NULL);
746 787
747 // Can use argv[1] directly, but this will mess up 788 // Can use argv[1] directly, but this will mess up
@@ -750,11 +791,11 @@ int nmeter_main(int argc, char **argv)
750 while (1) { 791 while (1) {
751 char *param, *p; 792 char *param, *p;
752 prev = cur; 793 prev = cur;
753again: 794 again:
754 cur = strchr(cur, '%'); 795 cur = strchr(cur, '%');
755 if (!cur) 796 if (!cur)
756 break; 797 break;
757 if (cur[1]=='%') { // %% 798 if (cur[1] == '%') { // %%
758 strcpy(cur, cur+1); 799 strcpy(cur, cur+1);
759 cur++; 800 cur++;
760 goto again; 801 goto again;
@@ -813,12 +854,12 @@ again:
813 collect_info(first); 854 collect_info(first);
814 reset_outbuf(); 855 reset_outbuf();
815 if (delta >= 0) { 856 if (delta >= 0) {
816 gettimeofday(&tv, 0); 857 gettimeofday(&tv, NULL);
817 usleep(delta > 1000000 ? 1000000 : delta - tv.tv_usec%deltanz); 858 usleep(delta > 1000000 ? 1000000 : delta - tv.tv_usec%deltanz);
818 } 859 }
819 860
820 while (1) { 861 while (1) {
821 gettimeofday(&tv, 0); 862 gettimeofday(&tv, NULL);
822 collect_info(first); 863 collect_info(first);
823 put(final_str); 864 put(final_str);
824 print_outbuf(); 865 print_outbuf();
@@ -831,9 +872,9 @@ again:
831 if (delta >= 0) { 872 if (delta >= 0) {
832 int rem; 873 int rem;
833 // can be commented out, will sacrifice sleep time precision a bit 874 // can be commented out, will sacrifice sleep time precision a bit
834 gettimeofday(&tv, 0); 875 gettimeofday(&tv, NULL);
835 if (need_seconds) 876 if (need_seconds)
836 rem = delta - ((ullong)tv.tv_sec*1000000+tv.tv_usec)%deltanz; 877 rem = delta - ((ullong)tv.tv_sec*1000000 + tv.tv_usec) % deltanz;
837 else 878 else
838 rem = delta - tv.tv_usec%deltanz; 879 rem = delta - tv.tv_usec%deltanz;
839 // Sometimes kernel wakes us up just a tiny bit earlier than asked 880 // Sometimes kernel wakes us up just a tiny bit earlier than asked
@@ -845,5 +886,5 @@ again:
845 } 886 }
846 } 887 }
847 888
848 return 0; 889 /*return 0;*/
849} 890}