From 749806b389f53f7dd43a2cae1589e63dddf51990 Mon Sep 17 00:00:00 2001 From: WaLyong Cho Date: Fri, 13 Feb 2015 14:59:39 +0900 Subject: [PATCH] bootchart: display each CPU utilization/wait --- src/bootchart/bootchart.c | 38 +++++++++++++-------- src/bootchart/bootchart.conf | 1 + src/bootchart/bootchart.h | 1 + src/bootchart/svg.c | 65 ++++++++++++++++++++++++------------ 4 files changed, 70 insertions(+), 35 deletions(-) diff --git a/src/bootchart/bootchart.c b/src/bootchart/bootchart.c index b49e2c923..64a384bac 100644 --- a/src/bootchart/bootchart.c +++ b/src/bootchart/bootchart.c @@ -87,6 +87,7 @@ bool arg_filter = true; bool arg_show_cmdline = false; bool arg_show_cgroup = false; bool arg_pss = false; +bool arg_percpu = false; int samples; int arg_samples_len = DEFAULT_SAMPLES_LEN; /* we record len+1 (1 start sample) */ double arg_hz = DEFAULT_HZ; @@ -122,6 +123,7 @@ static void parse_conf(void) { { "Bootchart", "ScaleX", config_parse_double, 0, &arg_scale_x }, { "Bootchart", "ScaleY", config_parse_double, 0, &arg_scale_y }, { "Bootchart", "ControlGroup", config_parse_bool, 0, &arg_show_cgroup }, + { "Bootchart", "PerCPU", config_parse_bool, 0, &arg_percpu }, { NULL, NULL, NULL, 0, NULL } }; @@ -151,6 +153,7 @@ static void help(void) { " -F, --no-filter Disable filtering of unimportant or ephemeral processes\n" " -C, --cmdline Display full command lines with arguments\n" " -c, --control-group Display process control group\n" + " --per-cpu Draw each CPU utilization and wait bar also\n" " -h, --help Display this message\n\n" "See bootchart.conf for more information.\n", program_invocation_short_name, @@ -163,20 +166,26 @@ static void help(void) { } static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_PERCPU = 0x100, + }; + static const struct option options[] = { - {"rel", no_argument, NULL, 'r'}, - {"freq", required_argument, NULL, 'f'}, - {"samples", required_argument, NULL, 'n'}, - {"pss", no_argument, NULL, 'p'}, - {"output", required_argument, NULL, 'o'}, - {"init", required_argument, NULL, 'i'}, - {"no-filter", no_argument, NULL, 'F'}, - {"cmdline", no_argument, NULL, 'C'}, - {"control-group", no_argument, NULL, 'c'}, - {"help", no_argument, NULL, 'h'}, - {"scale-x", required_argument, NULL, 'x'}, - {"scale-y", required_argument, NULL, 'y'}, - {"entropy", no_argument, NULL, 'e'}, + {"rel", no_argument, NULL, 'r' }, + {"freq", required_argument, NULL, 'f' }, + {"samples", required_argument, NULL, 'n' }, + {"pss", no_argument, NULL, 'p' }, + {"output", required_argument, NULL, 'o' }, + {"init", required_argument, NULL, 'i' }, + {"no-filter", no_argument, NULL, 'F' }, + {"cmdline", no_argument, NULL, 'C' }, + {"control-group", no_argument, NULL, 'c' }, + {"help", no_argument, NULL, 'h' }, + {"scale-x", required_argument, NULL, 'x' }, + {"scale-y", required_argument, NULL, 'y' }, + {"entropy", no_argument, NULL, 'e' }, + {"per-cpu", no_argument, NULL, ARG_PERCPU}, {} }; int c, r; @@ -237,6 +246,9 @@ static int parse_argv(int argc, char *argv[]) { case 'e': arg_entropy = true; break; + case ARG_PERCPU: + arg_percpu = true; + break; case 'h': help(); return 0; diff --git a/src/bootchart/bootchart.conf b/src/bootchart/bootchart.conf index c73328fde..2d7cb6121 100644 --- a/src/bootchart/bootchart.conf +++ b/src/bootchart/bootchart.conf @@ -22,3 +22,4 @@ #ScaleX=100 #ScaleY=20 #ControlGroup=no +#PerCPU=no diff --git a/src/bootchart/bootchart.h b/src/bootchart/bootchart.h index 2c3783580..26de0dd9f 100644 --- a/src/bootchart/bootchart.h +++ b/src/bootchart/bootchart.h @@ -118,6 +118,7 @@ extern bool arg_show_cmdline; extern bool arg_show_cgroup; extern bool arg_pss; extern bool arg_entropy; +extern bool arg_percpu; extern bool initcall; extern int samples; extern int cpus; diff --git a/src/bootchart/svg.c b/src/bootchart/svg.c index e5569e162..e111fa9cc 100644 --- a/src/bootchart/svg.c +++ b/src/bootchart/svg.c @@ -749,11 +749,14 @@ static void svg_io_bo_bar(void) { } } -static void svg_cpu_bar(void) { +static void svg_cpu_bar(int cpu_num) { svg("\n"); - svg("CPU utilization\n"); + if (cpu_num < 0) + svg("CPU[overall] utilization\n"); + else + svg("CPU[%d] utilization\n", cpu_num); /* surrounding box */ svg_graph_box(5); @@ -766,12 +769,16 @@ static void svg_cpu_bar(void) { ptrt = trt = 0.0; - for (c = 0; c < cpus; c++) - trt += sampledata->runtime[c] - prev_sampledata->runtime[c]; + if (cpu_num < 0) + for (c = 0; c < cpus; c++) + trt += sampledata->runtime[c] - prev_sampledata->runtime[c]; + else + trt = sampledata->runtime[cpu_num] - prev_sampledata->runtime[cpu_num]; trt = trt / 1000000000.0; - trt = trt / (double)cpus; + if (cpu_num < 0) + trt = trt / (double)cpus; if (trt > 0.0) ptrt = trt / (sampledata->sampletime - prev_sampledata->sampletime); @@ -790,11 +797,14 @@ static void svg_cpu_bar(void) { } } -static void svg_wait_bar(void) { +static void svg_wait_bar(int cpu_num) { svg("\n"); - svg("CPU wait\n"); + if (cpu_num < 0) + svg("CPU[overall] wait\n"); + else + svg("CPU[%d] wait\n", cpu_num); /* surrounding box */ svg_graph_box(5); @@ -808,12 +818,16 @@ static void svg_wait_bar(void) { ptwt = twt = 0.0; - for (c = 0; c < cpus; c++) - twt += sampledata->waittime[c] - prev_sampledata->waittime[c]; + if (cpu_num < 0) + for (c = 0; c < cpus; c++) + twt += sampledata->waittime[c] - prev_sampledata->waittime[c]; + else + twt = sampledata->waittime[cpu_num] - prev_sampledata->waittime[cpu_num]; twt = twt / 1000000000.0; - twt = twt / (double)cpus; + if (cpu_num < 0) + twt = twt / (double)cpus; if (twt > 0.0) ptwt = twt / (sampledata->sampletime - prev_sampledata->sampletime); @@ -832,7 +846,6 @@ static void svg_wait_bar(void) { } } - static void svg_entropy_bar(void) { svg("\n"); @@ -1256,6 +1269,8 @@ static void svg_top_ten_pss(void) { void svg_do(const char *build) { struct ps_struct *ps; + double offset = 7; + int c; memzero(&str, sizeof(str)); @@ -1284,25 +1299,31 @@ void svg_do(const char *build) { svg_io_bi_bar(); svg("\n\n"); - svg("\n", 400.0 + (arg_scale_y * 7.0)); + svg("\n", 400.0 + (arg_scale_y * offset)); svg_io_bo_bar(); svg("\n\n"); - svg("\n", 400.0 + (arg_scale_y * 14.0)); - svg_cpu_bar(); - svg("\n\n"); + for (c = -1; c < (arg_percpu ? cpus : 0); c++) { + offset += 7; + svg("\n", 400.0 + (arg_scale_y * offset)); + svg_cpu_bar(c); + svg("\n\n"); - svg("\n", 400.0 + (arg_scale_y * 21.0)); - svg_wait_bar(); - svg("\n\n"); + offset += 7; + svg("\n", 400.0 + (arg_scale_y * offset)); + svg_wait_bar(c); + svg("\n\n"); + } if (kcount) { - svg("\n", 400.0 + (arg_scale_y * 28.0)); + offset += 7; + svg("\n", 400.0 + (arg_scale_y * offset)); svg_do_initcall(0); svg("\n\n"); } - svg("\n", 400.0 + (arg_scale_y * 28.0) + ksize); + offset += 7; + svg("\n", 400.0 + (arg_scale_y * offset) + ksize); svg_ps_bars(); svg("\n\n"); @@ -1315,13 +1336,13 @@ void svg_do(const char *build) { svg("\n\n"); if (arg_entropy) { - svg("\n", 400.0 + (arg_scale_y * 28.0) + ksize + psize); + svg("\n", 400.0 + (arg_scale_y * offset) + ksize + psize); svg_entropy_bar(); svg("\n\n"); } if (arg_pss) { - svg("\n", 400.0 + (arg_scale_y * 28.0) + ksize + psize + esize); + svg("\n", 400.0 + (arg_scale_y * offset) + ksize + psize + esize); svg_pss_graph(); svg("\n\n"); -- 2.30.2