diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-05-30 14:48:38 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-05-30 14:48:38 +0000 |
commit | 199c0d542b51b55b99dddc1742c23325288f79eb (patch) | |
tree | e96bc50264dc59c14d0a32aa4d84384439dd4586 | |
parent | 0b3b41b62acd6c2911ea4f08e0dd96f93334aff5 (diff) | |
download | busybox-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.c | 137 |
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 | ||
18 | typedef unsigned long long ullong; | 18 | typedef unsigned long long ullong; |
19 | 19 | ||
20 | enum { proc_file_size = 4096 }; | 20 | enum { PROC_FILE_SIZE = 4096 }; |
21 | 21 | ||
22 | typedef struct proc_file { | 22 | typedef 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 | ||
28 | static proc_file proc_stat = { "/proc/stat", -1 }; | 28 | static const char *const proc_name[] = { |
29 | static proc_file proc_loadavg = { "/proc/loadavg", -1 }; | 29 | "stat", // Must match the order of proc_file's! |
30 | static proc_file proc_net_dev = { "/proc/net/dev", -1 }; | 30 | "loadavg", |
31 | static proc_file proc_meminfo = { "/proc/meminfo", -1 }; | 31 | "net/dev", |
32 | static proc_file proc_diskstats = { "/proc/diskstats", -1 }; | 32 | "meminfo", |
33 | // Sample # | 33 | "diskstats", |
34 | static int gen = -1; | 34 | "sys/fs/file-nr", |
35 | // Linux 2.6? (otherwise assumes 2.4) | 35 | }; |
36 | static int is26 = 0; | 36 | |
37 | static struct timeval tv; | 37 | struct globals { |
38 | static int delta = 1000000; | 38 | // Sample generation flip-flop |
39 | static int deltanz = 1000000; | 39 | smallint gen; |
40 | static int need_seconds = 0; | 40 | // Linux 2.6? (otherwise assumes 2.4) |
41 | static 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 |
45 | static 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 | ||
48 | static inline void reset_outbuf(void) | 82 | static 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 | ||
88 | static int readfile_z(char *buf, int sz, const char* fname) | 122 | static 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 | ||
99 | static const char* get_file(proc_file *pf) | 137 | static 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 | ||
243 | static s_stat* init_delay(const char *param) | 281 | static 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 | ||
251 | static s_stat* init_cr(const char *param) | 289 | static 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 | ||
641 | static void collect_fd(fd_stat *s) | 679 | static 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 | ||
703 | static void collect_info(s_stat *s) | 739 | static 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) | |||
714 | typedef s_stat* init_func(const char *param); | 750 | typedef s_stat* init_func(const char *param); |
715 | 751 | ||
716 | static const char options[] = "ncmsfixptbdr"; | 752 | static const char options[] = "ncmsfixptbdr"; |
717 | static init_func* init_functions[] = { | 753 | static 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; |
753 | again: | 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 | } |