diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-06-11 16:31:55 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-06-11 16:31:55 +0000 |
commit | 745119605e2ecdffad1def6aaabfc8f6d270209e (patch) | |
tree | 9fadde8f219f0ade210faf00fc71a884d6088309 /procps | |
parent | d71e45856eb0788024aa84d6bc594940f678bcd2 (diff) | |
download | busybox-w32-745119605e2ecdffad1def6aaabfc8f6d270209e.tar.gz busybox-w32-745119605e2ecdffad1def6aaabfc8f6d270209e.tar.bz2 busybox-w32-745119605e2ecdffad1def6aaabfc8f6d270209e.zip |
top: on user suggestion make percentile calculations configurable. -56 bytes when off. +600 bytes when on
top: reorder columns, so that [P]PIDs are together and VSZ/%MEM are together. Makes more sense
Diffstat (limited to 'procps')
-rw-r--r-- | procps/Config.in | 9 | ||||
-rw-r--r-- | procps/top.c | 100 |
2 files changed, 71 insertions, 38 deletions
diff --git a/procps/Config.in b/procps/Config.in index fba9e4074..91319103f 100644 --- a/procps/Config.in +++ b/procps/Config.in | |||
@@ -109,12 +109,19 @@ config FEATURE_TOP_CPU_USAGE_PERCENTAGE | |||
109 | Make top display CPU usage for each process. | 109 | Make top display CPU usage for each process. |
110 | 110 | ||
111 | config FEATURE_TOP_CPU_GLOBAL_PERCENTS | 111 | config FEATURE_TOP_CPU_GLOBAL_PERCENTS |
112 | bool "Show CPU global usage percentage (adds 0.5k byte)" | 112 | bool "Show CPU global usage percentage (adds 0.5k bytes)" |
113 | default y | 113 | default y |
114 | depends on FEATURE_TOP_CPU_USAGE_PERCENTAGE | 114 | depends on FEATURE_TOP_CPU_USAGE_PERCENTAGE |
115 | help | 115 | help |
116 | Makes top display "CPU: NN% usr NN% sys..." line. | 116 | Makes top display "CPU: NN% usr NN% sys..." line. |
117 | 117 | ||
118 | config FEATURE_TOP_DECIMALS | ||
119 | bool "Show 1/10th of a percent in CPU/mem statistics (adds 0.5k bytes)" | ||
120 | default n | ||
121 | depends on FEATURE_TOP_CPU_USAGE_PERCENTAGE | ||
122 | help | ||
123 | Show 1/10th of a percent in CPU/mem statistics. | ||
124 | |||
118 | config UPTIME | 125 | config UPTIME |
119 | bool "uptime" | 126 | bool "uptime" |
120 | default n | 127 | default n |
diff --git a/procps/top.c b/procps/top.c index 564e94343..c6efe2d77 100644 --- a/procps/top.c +++ b/procps/top.c | |||
@@ -293,14 +293,16 @@ static unsigned long display_generic(int scr_width) | |||
293 | * xxx% = (jif.xxx - prev_jif.xxx) / (jif.total - prev_jif.total) * 100% | 293 | * xxx% = (jif.xxx - prev_jif.xxx) / (jif.total - prev_jif.total) * 100% |
294 | */ | 294 | */ |
295 | /* using (unsigned) cast to make multiplication cheaper: */ | 295 | /* using (unsigned) cast to make multiplication cheaper: */ |
296 | #if ENABLE_FEATURE_TOP_DECIMALS | ||
297 | /* Generated code is approx +0.5k */ | ||
298 | #define CALC_STAT(xxx) div_t xxx = div(1000 * (unsigned)(jif.xxx - prev_jif.xxx) / total_diff, 10) | ||
299 | #define SHOW_STAT(xxx) xxx.quot, '0'+xxx.rem | ||
300 | #define FMT "%3u.%c%%" | ||
301 | #else | ||
296 | #define CALC_STAT(xxx) unsigned xxx = 100 * (unsigned)(jif.xxx - prev_jif.xxx) / total_diff | 302 | #define CALC_STAT(xxx) unsigned xxx = 100 * (unsigned)(jif.xxx - prev_jif.xxx) / total_diff |
297 | #define SHOW_STAT(xxx) xxx | 303 | #define SHOW_STAT(xxx) xxx |
298 | #define FMT "%3u%%" | 304 | #define FMT "%3u%%" |
299 | // We can display fractional percents, but at least in glibc div() is a _function_ | 305 | #endif |
300 | // and generated code is really awful and big (+0.5k more code): | ||
301 | //#define CALC_STAT(xxx) div_t xxx = div(1000 * (unsigned)(jif.xxx - prev_jif.xxx) / total_diff, 10) | ||
302 | //#define SHOW_STAT(xxx) xxx.quot, '0'+xxx.rem | ||
303 | //#define FMT "%3u.%c%%" | ||
304 | unsigned total_diff = (jif.total - prev_jif.total ? : 1); | 306 | unsigned total_diff = (jif.total - prev_jif.total ? : 1); |
305 | CALC_STAT(usr); | 307 | CALC_STAT(usr); |
306 | CALC_STAT(sys); | 308 | CALC_STAT(sys); |
@@ -312,14 +314,14 @@ static unsigned long display_generic(int scr_width) | |||
312 | //CALC_STAT(steal); | 314 | //CALC_STAT(steal); |
313 | 315 | ||
314 | snprintf(scrbuf, scr_width, | 316 | snprintf(scrbuf, scr_width, |
315 | /* %3u in practice almost never displays "100" | 317 | /* Barely fits in 79 chars when in "decimals" mode. |
318 | * %3u in practice almost never displays "100" | ||
316 | * and thus has implicit leading space: " 99" */ | 319 | * and thus has implicit leading space: " 99" */ |
317 | "CPU:"FMT" usr"FMT" sys"FMT" nice"FMT" idle"FMT" wait"FMT" irq"FMT" softirq", | 320 | "CPU:"FMT" usr"FMT" sys"FMT" nice"FMT" idle"FMT" io"FMT" irq"FMT" softirq", |
318 | // FMT" steal", - what is this 'steal' thing? | ||
319 | // I doubt anyone needs to know it | ||
320 | SHOW_STAT(usr), SHOW_STAT(sys), SHOW_STAT(nic), SHOW_STAT(idle), | 321 | SHOW_STAT(usr), SHOW_STAT(sys), SHOW_STAT(nic), SHOW_STAT(idle), |
321 | SHOW_STAT(iowait), SHOW_STAT(irq), SHOW_STAT(softirq) | 322 | SHOW_STAT(iowait), SHOW_STAT(irq), SHOW_STAT(softirq) |
322 | //, SHOW_STAT(steal) | 323 | //, SHOW_STAT(steal) - what is this 'steal' thing? |
324 | // I doubt anyone wants to know it | ||
323 | ); | 325 | ); |
324 | puts(scrbuf); | 326 | puts(scrbuf); |
325 | #undef SHOW_STAT | 327 | #undef SHOW_STAT |
@@ -333,45 +335,59 @@ static unsigned long display_generic(int scr_width) | |||
333 | return total; | 335 | return total; |
334 | } | 336 | } |
335 | 337 | ||
336 | 338 | #if ENABLE_FEATURE_TOP_DECIMALS | |
339 | #define UPSCALE 1000 | ||
340 | #define CALC_STAT(name, val) div_t name = div((val), 10) | ||
341 | #define SHOW_STAT(name) name.quot, '0'+name.rem | ||
342 | #define FMT "%3u.%c" | ||
343 | #else | ||
344 | #define UPSCALE 100 | ||
345 | #define CALC_STAT(name, val) unsigned name = (val) | ||
346 | #define SHOW_STAT(name) name | ||
347 | #define FMT " %3u%%" | ||
348 | #endif | ||
337 | /* display process statuses */ | 349 | /* display process statuses */ |
338 | static void display_status(int count, int scr_width) | 350 | static void display_status(int count, int scr_width) |
339 | { | 351 | { |
340 | enum { | 352 | enum { |
341 | bits_per_int = sizeof(int)*8 | 353 | BITS_PER_INT = sizeof(int)*8 |
342 | }; | 354 | }; |
343 | 355 | ||
344 | top_status_t *s = top; | 356 | top_status_t *s = top; |
345 | char vsz_str_buf[8]; | 357 | char vsz_str_buf[8]; |
346 | unsigned long total_memory = display_generic(scr_width); /* or use total_vsz? */ | 358 | unsigned long total_memory = display_generic(scr_width); /* or use total_vsz? */ |
347 | unsigned pmem_shift, pmem_scale; | 359 | /* xxx_shift and xxx_scale variables allow us to replace |
348 | 360 | * expensive divides with multiply and shift */ | |
361 | unsigned pmem_shift, pmem_scale, pmem_half; | ||
349 | #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE | 362 | #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE |
350 | unsigned pcpu_shift, pcpu_scale; | 363 | unsigned pcpu_shift, pcpu_scale, pcpu_half; |
351 | unsigned busy_jifs; | 364 | unsigned busy_jifs; |
352 | 365 | ||
353 | /* what info of the processes is shown */ | 366 | /* what info of the processes is shown */ |
354 | printf(OPT_BATCH_MODE ? "%.*s" : "\e[7m%.*s\e[0m", scr_width, | 367 | printf(OPT_BATCH_MODE ? "%.*s" : "\e[7m%.*s\e[0m", scr_width, |
355 | " PID USER STATUS VSZ PPID %CPU %MEM COMMAND"); | 368 | " PID PPID USER STAT VSZ %MEM %CPU COMMAND"); |
356 | #define MIN_WIDTH \ | 369 | #define MIN_WIDTH \ |
357 | sizeof( " PID USER STATUS VSZ PPID %CPU %MEM C") | 370 | sizeof( " PID PPID USER STAT VSZ %MEM %CPU C") |
358 | #else | 371 | #else |
372 | |||
373 | /* !CPU_USAGE_PERCENTAGE */ | ||
359 | printf(OPT_BATCH_MODE ? "%.*s" : "\e[7m%.*s\e[0m", scr_width, | 374 | printf(OPT_BATCH_MODE ? "%.*s" : "\e[7m%.*s\e[0m", scr_width, |
360 | " PID USER STATUS VSZ PPID %MEM COMMAND"); | 375 | " PID PPID USER STAT VSZ %MEM COMMAND"); |
361 | #define MIN_WIDTH \ | 376 | #define MIN_WIDTH \ |
362 | sizeof( " PID USER STATUS VSZ PPID %MEM C") | 377 | sizeof( " PID PPID USER STAT VSZ %MEM C") |
363 | #endif | 378 | #endif |
364 | 379 | ||
365 | /* | 380 | /* |
366 | * MEM% = s->vsz/MemTotal | 381 | * MEM% = s->vsz/MemTotal |
367 | */ | 382 | */ |
368 | pmem_shift = bits_per_int-11; | 383 | pmem_shift = BITS_PER_INT-11; |
369 | pmem_scale = 1000*(1U<<(bits_per_int-11)) / total_memory; | 384 | pmem_scale = UPSCALE*(1U<<(BITS_PER_INT-11)) / total_memory; |
370 | /* s->vsz is in kb. we want (s->vsz * pmem_scale) to never overflow */ | 385 | /* s->vsz is in kb. we want (s->vsz * pmem_scale) to never overflow */ |
371 | while (pmem_scale >= 512) { | 386 | while (pmem_scale >= 512) { |
372 | pmem_scale /= 4; | 387 | pmem_scale /= 4; |
373 | pmem_shift -= 2; | 388 | pmem_shift -= 2; |
374 | } | 389 | } |
390 | pmem_half = (1U << pmem_shift) / (ENABLE_FEATURE_TOP_DECIMALS? 20 : 2); | ||
375 | #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE | 391 | #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE |
376 | busy_jifs = jif.busy - prev_jif.busy; | 392 | busy_jifs = jif.busy - prev_jif.busy; |
377 | /* This happens if there were lots of short-lived processes | 393 | /* This happens if there were lots of short-lived processes |
@@ -387,8 +403,8 @@ static void display_status(int count, int scr_width) | |||
387 | * we assume that unsigned is at least 32-bit. | 403 | * we assume that unsigned is at least 32-bit. |
388 | */ | 404 | */ |
389 | pcpu_shift = 6; | 405 | pcpu_shift = 6; |
390 | pcpu_scale = (1000*64*(uint16_t)busy_jifs ? : 1); | 406 | pcpu_scale = (UPSCALE*64*(uint16_t)busy_jifs ? : 1); |
391 | while (pcpu_scale < (1U<<(bits_per_int-2))) { | 407 | while (pcpu_scale < (1U<<(BITS_PER_INT-2))) { |
392 | pcpu_scale *= 4; | 408 | pcpu_scale *= 4; |
393 | pcpu_shift += 2; | 409 | pcpu_shift += 2; |
394 | } | 410 | } |
@@ -398,28 +414,35 @@ static void display_status(int count, int scr_width) | |||
398 | pcpu_scale /= 4; | 414 | pcpu_scale /= 4; |
399 | pcpu_shift -= 2; | 415 | pcpu_shift -= 2; |
400 | } | 416 | } |
417 | pcpu_half = (1U << pcpu_shift) / (ENABLE_FEATURE_TOP_DECIMALS? 20 : 2); | ||
401 | /* printf(" pmem_scale=%u pcpu_scale=%u ", pmem_scale, pcpu_scale); */ | 418 | /* printf(" pmem_scale=%u pcpu_scale=%u ", pmem_scale, pcpu_scale); */ |
402 | #endif | 419 | #endif |
420 | |||
421 | /* Ok, all prelim data is ready, go thru the list */ | ||
403 | while (count-- > 0) { | 422 | while (count-- > 0) { |
404 | div_t pmem = div((s->vsz*pmem_scale) >> pmem_shift, 10); | ||
405 | int col = scr_width+1; | 423 | int col = scr_width+1; |
406 | USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE(div_t pcpu;) | 424 | CALC_STAT(pmem, (s->vsz*pmem_scale + pmem_half) >> pmem_shift); |
425 | #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE | ||
426 | CALC_STAT(pcpu, (s->pcpu*pcpu_scale + pcpu_half) >> pcpu_shift); | ||
427 | #endif | ||
407 | 428 | ||
408 | if (s->vsz >= 100*1024) | 429 | if (s->vsz >= 100*1024) |
409 | sprintf(vsz_str_buf, "%6ldM", s->vsz/1024); | 430 | sprintf(vsz_str_buf, "%6ldM", s->vsz/1024); |
410 | else | 431 | else |
411 | sprintf(vsz_str_buf, "%7ld", s->vsz); | 432 | sprintf(vsz_str_buf, "%7ld", s->vsz); |
412 | USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE( | 433 | // PID PPID USER STAT VSZ %MEM [%CPU] COMMAND |
413 | pcpu = div((s->pcpu*pcpu_scale) >> pcpu_shift, 10); | 434 | col -= printf("\n" "%5u%6u %-8s %s%s" FMT |
414 | ) | 435 | #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE |
415 | col -= printf("\n%5u %-8s %s " | 436 | FMT |
416 | "%s%6u" | 437 | #endif |
417 | USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE("%3u.%c") | 438 | " ", |
418 | "%3u.%c ", | 439 | s->pid, s->ppid, get_cached_username(s->uid), |
419 | s->pid, get_cached_username(s->uid), s->state, | 440 | s->state, vsz_str_buf, |
420 | vsz_str_buf, s->ppid, | 441 | SHOW_STAT(pmem) |
421 | USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE(pcpu.quot, '0'+pcpu.rem,) | 442 | #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE |
422 | pmem.quot, '0'+pmem.rem); | 443 | , SHOW_STAT(pcpu) |
444 | #endif | ||
445 | ); | ||
423 | if (col > 0) | 446 | if (col > 0) |
424 | printf("%.*s", col, s->comm); | 447 | printf("%.*s", col, s->comm); |
425 | /* printf(" %d/%d %lld/%lld", s->pcpu, total_pcpu, | 448 | /* printf(" %d/%d %lld/%lld", s->pcpu, total_pcpu, |
@@ -430,6 +453,9 @@ static void display_status(int count, int scr_width) | |||
430 | putchar(OPT_BATCH_MODE ? '\n' : '\r'); | 453 | putchar(OPT_BATCH_MODE ? '\n' : '\r'); |
431 | fflush(stdout); | 454 | fflush(stdout); |
432 | } | 455 | } |
456 | #undef SHOW_STAT | ||
457 | #undef CALC_STAT | ||
458 | #undef FMT | ||
433 | 459 | ||
434 | 460 | ||
435 | static void clearmems(void) | 461 | static void clearmems(void) |
@@ -549,7 +575,7 @@ int top_main(int argc, char **argv) | |||
549 | strcpy(top[n].comm, p->comm); | 575 | strcpy(top[n].comm, p->comm); |
550 | } | 576 | } |
551 | if (ntop == 0) { | 577 | if (ntop == 0) { |
552 | bb_error_msg_and_die("can't find process info in /proc"); | 578 | bb_error_msg_and_die("no process info in /proc"); |
553 | } | 579 | } |
554 | #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE | 580 | #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE |
555 | if (!prev_hist_count) { | 581 | if (!prev_hist_count) { |