diff options
author | Koan-Sin Tan <freedom.tan@linaro.org> | 2014-11-27 17:10:48 +0800 |
---|---|---|
committer | Tuukka Tikkanen <tuukka.tikkanen@linaro.org> | 2014-11-28 05:43:51 +0200 |
commit | 62924570fcb8a84040ecfd02b280366fdb2cf7e8 (patch) | |
tree | 83c032115714d204d2ccd427a463820c922b64cf | |
parent | db63259a01cb3c88b82dbecddd48a2c166c84e20 (diff) |
Add CSV report formats
1. add csv report ops in csv_report.c
2. add -C option
3. add simple description in csv-format.txt
Signed-off-by: Koan-Sin Tan <freedom.tan@linaro.org>
Signed-off-by: Tuukka Tikkanen <tuukka.tikkanen@linaro.org>
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | csv-format.txt | 62 | ||||
-rw-r--r-- | csv_report.c | 128 | ||||
-rw-r--r-- | idlestat.c | 8 | ||||
-rw-r--r-- | report_ops.h | 1 |
5 files changed, 199 insertions, 2 deletions
@@ -24,7 +24,7 @@ CFLAGS?=-g -Wall CC=gcc -OBJS = idlestat.o topology.o trace.o utils.o energy_model.o default_report.o +OBJS = idlestat.o topology.o trace.o utils.o energy_model.o default_report.o csv_report.o default: idlestat diff --git a/csv-format.txt b/csv-format.txt new file mode 100644 index 0000000..1bb13a4 --- /dev/null +++ b/csv-format.txt @@ -0,0 +1,62 @@ +The CSV output is intended as an alternative to default output format to +facilitate easy importing into spreadsheet applications or further +processing with scripts. + +The file contains one or more of the tables (C-state/P-state/wakeups). In +case of multiple tables, they are separated by empty lines. + +For each table, the first line is the name of the table, i.e. one of +C-State Table +P-State Table +Wakeup Table + +The second line is a header line that describes the names of fields in the +table., E.g. +cluster,core,cpu,C-state,min (us),max (us),avg (us),total (us),hits,over,under + +The following lines are either topological names or data entries. The data +may relate to a cluster (package), a core (collection of hyperthreaded cpus) +or a cpu. A cpu belongs to a core (hyperthreading) or a cluster (no ht). +A core always belongs to a cluster. + +Topology names: +Cluster names are in the first column and all other columns are missing. +Core names (if present) are in the second column and all subsequent +columns are missing. The first column is empty. +Cpu names (regardless of existence of core layer) are in the third column +and all subsequent columns are missing. The first and second columns +are empty. + +Data lines: +Each data line begins with 3 empty columns (reserved for topological names) +and are followed by report-specific values. For meaning of the columns, +refer to the header line for the report. + + +PARTIAL EXAMPLE (idle state data): + +C-State Table +cluster,core,cpu,C-state,min (us),max (us),avg (us),total (us),hits,over,under +clusterA +,,,C6-IVB,0.000000,16739.001498,11564.733154,14953199.967742,1293,0,0 +,core0 +,,,C6-IVB,0.000000,16739.001498,12625.515565,14986486.975104,1187,0,0 +,,cpu0 +,,,C1-IVB,17.000362,19.999221,18.333395,55.000186,3,0,0 +,,,C3-IVB,307.999551,5589.000881,2948.500216,5897.000432,2,0,2 +,,,C6-IVB,70.000067,16741.000116,14009.491556,14990155.965090,1070,17,0 +,,cpu4 +,,,C6-IVB,16.000122,297569.001094,126147.353020,15011535.009369,119,8,0 +(more cores and cpus follow) + +The cluster A has been in C6-IVB state for a total of 14.95 seconds +during 1293 separate idle periods. + +The core 0 (belonging to cluster A) has been in C6-IVB for a total of +14.99 seconds during 1187 separate idle periods. + +The cpu 0 (belonging to core 0) has been in 3 different idle states as +detailed. + +The cpu 4 (belonging to core 0) has been in C6-IVB for a total of +15.01 seconds. diff --git a/csv_report.c b/csv_report.c new file mode 100644 index 0000000..f910cf2 --- /dev/null +++ b/csv_report.c @@ -0,0 +1,128 @@ +#include <float.h> +#include <stdbool.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include "idlestat.h" +#include "utils.h" + +static int csv_check_output(struct program_options *options, void *report_data) +{ + return 0; +} + +static int csv_open_report_file(char *path, void *report_data) +{ + return redirect_stdout_to_file(path); +} + +static int csv_close_report_file(void *report_data) +{ + return (fclose(stdout) == EOF) ? -1 : 0; +} + +static void csv_cstate_table_header(void *report_data) +{ + printf("C-State Table\n"); + printf("cluster,core,cpu,C-state,min (us),max (us),avg (us),total (us),hits,over,under\n"); +} + +static void csv_cstate_table_footer(void *report_data) +{ + printf("\n\n"); +} + +static void csv_cstate_cpu_header(const char *cpu, void *report_data) +{ + if (strstr(cpu, "cluster")) + printf("%s\n", cpu); + else if (strstr(cpu, "core")) + printf(",%s\n", cpu); + else printf(",,%s\n", cpu); +} + +static void csv_cstate_single_state(struct cpuidle_cstate *c, void *report_data) +{ + printf(",,,%s,", c->name); + printf("%f,", c->min_time == DBL_MAX ? 0. : c->min_time); + printf("%f,%f,%f,", c->max_time, c->avg_time, c->duration); + printf("%d,%d,%d", c->nrdata, c->early_wakings, c->late_wakings); + + printf("\n"); +} + +static void csv_cstate_end_cpu(void *report_data) +{ +} + +static void csv_pstate_table_header(void *report_data) +{ + printf("P-State Table\n"); + printf(",,,P-state (kHz),min (us),max (us),avg (us),total (us),hits\n"); +} + +static void csv_pstate_table_footer(void *report_data) +{ + printf("\n\n"); +} + +static void csv_pstate_single_state(struct cpufreq_pstate *p, void *report_data) +{ + printf(",,,%d,", p->freq); + printf("%f,", p->min_time == DBL_MAX ? 0. : p->min_time); + printf("%f,%f,%f,", p->max_time, p->avg_time, p->duration); + printf("%d", p->count); + + printf("\n"); +} + +static void csv_wakeup_table_header(void *report_data) +{ + printf("\n"); + + printf("Wakeup Table\n"); + printf("cluster,core,cpu,IRQ,Name,Count,early,late\n"); +} + +static void csv_wakeup_table_footer(void *report_data) +{ + printf("\n\n"); +} + +static void csv_wakeup_single_state(struct wakeup_irq *irqinfo, void *report_data) +{ + if (irqinfo->id != -1) { + printf(",,,%d,%s,%d,%d,%d\n", + irqinfo->id, irqinfo->name, irqinfo->count, + irqinfo->early_triggers, irqinfo->late_triggers); + } else { + printf(",,,IPI,%s,%d,%d,%d\n", + irqinfo->name, irqinfo->count, + irqinfo->early_triggers, irqinfo->late_triggers); + } +} + +struct report_ops csv_report_ops = { + .check_output = csv_check_output, + + .open_report_file = csv_open_report_file, + .close_report_file = csv_close_report_file, + + .cstate_table_header = csv_cstate_table_header, + .cstate_table_footer = csv_cstate_table_footer, + .cstate_cpu_header = csv_cstate_cpu_header, + .cstate_single_state = csv_cstate_single_state, + .cstate_end_cpu = csv_cstate_end_cpu, + + .pstate_table_header = csv_pstate_table_header, + .pstate_table_footer = csv_pstate_table_footer, + .pstate_cpu_header = csv_cstate_cpu_header, + .pstate_single_state = csv_pstate_single_state, + .pstate_end_cpu = csv_cstate_end_cpu, + + .wakeup_table_header = csv_wakeup_table_header, + .wakeup_table_footer = csv_wakeup_table_footer, + .wakeup_cpu_header = csv_cstate_cpu_header, + .wakeup_single_state = csv_wakeup_single_state, + .wakeup_end_cpu = csv_cstate_end_cpu, +}; @@ -1211,9 +1211,11 @@ static void help(const char *cmd) fprintf(stderr, "\nUsage:\nTrace mode:\n\t%s --trace -f|--trace-file <filename>" " -o|--output-file <filename> -t|--duration <seconds>" + " -C|--csv-report" " -c|--idle -p|--frequency -w|--wakeup", basename(cmd)); fprintf(stderr, "\nReporting mode:\n\t%s --import -f|--trace-file <filename>" + " -C|--csv-report" " -o|--output-file <filename>", basename(cmd)); fprintf(stderr, "\n\nExamples:\n1. Run a trace, post-process the results" @@ -1256,6 +1258,7 @@ int getoptions(int argc, char *argv[], struct program_options *options) { "frequency", no_argument, NULL, 'p' }, { "wakeup", no_argument, NULL, 'w' }, { "energy-model-file", required_argument, NULL, 'e' }, + { "csv-report", no_argument, NULL, 'C' }, { 0, 0, 0, 0 } }; int c; @@ -1271,7 +1274,7 @@ int getoptions(int argc, char *argv[], struct program_options *options) int optindex = 0; - c = getopt_long(argc, argv, ":de:f:o:ht:cpwVv", + c = getopt_long(argc, argv, ":de:f:o:ht:cpwVvC", long_options, &optindex); if (c == -1) break; @@ -1309,6 +1312,9 @@ int getoptions(int argc, char *argv[], struct program_options *options) case 'e': options->energy_model_filename = optarg; break; + case 'C': + options->report_ops = &csv_report_ops; + break; case 0: /* getopt_long() set a variable, just keep going */ break; case ':': /* missing option argument */ diff --git a/report_ops.h b/report_ops.h index 96222ac..ad77b2e 100644 --- a/report_ops.h +++ b/report_ops.h @@ -2,5 +2,6 @@ #define __REPORT_OPS_H extern struct report_ops default_report_ops; +extern struct report_ops csv_report_ops; #endif |