aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKoan-Sin Tan <freedom.tan@linaro.org>2014-11-27 17:10:48 +0800
committerTuukka Tikkanen <tuukka.tikkanen@linaro.org>2014-11-28 05:43:51 +0200
commit62924570fcb8a84040ecfd02b280366fdb2cf7e8 (patch)
tree83c032115714d204d2ccd427a463820c922b64cf
parentdb63259a01cb3c88b82dbecddd48a2c166c84e20 (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--Makefile2
-rw-r--r--csv-format.txt62
-rw-r--r--csv_report.c128
-rw-r--r--idlestat.c8
-rw-r--r--report_ops.h1
5 files changed, 199 insertions, 2 deletions
diff --git a/Makefile b/Makefile
index d520918..4abf57a 100644
--- a/Makefile
+++ b/Makefile
@@ -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,
+};
diff --git a/idlestat.c b/idlestat.c
index 7b6df02..98de74d 100644
--- a/idlestat.c
+++ b/idlestat.c
@@ -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