diff mbox series

[rt-tests,v4,12/12] rt-migrate-test: Add JSON output feature

Message ID 20210126091946.1241-13-dwagner@suse.de
State Superseded
Headers show
Series Generate machine-readable output | expand

Commit Message

Daniel Wagner Jan. 26, 2021, 9:19 a.m. UTC
Write the test results as JSON output to a file. This allows to
simplifies any parsing later on.

Signed-off-by: Daniel Wagner <dwagner@suse.de>
---
 src/rt-migrate-test/rt-migrate-test.c | 118 +++++++++++++++++++++-----
 1 file changed, 99 insertions(+), 19 deletions(-)
diff mbox series

Patch

diff --git a/src/rt-migrate-test/rt-migrate-test.c b/src/rt-migrate-test/rt-migrate-test.c
index 9bf716c9178c..9d34b3c7da52 100644
--- a/src/rt-migrate-test/rt-migrate-test.c
+++ b/src/rt-migrate-test/rt-migrate-test.c
@@ -19,11 +19,12 @@ 
 #include <fcntl.h>
 #include <signal.h>
 #include <sys/time.h>
-#include <linux/unistd.h>
 #include <sys/syscall.h>
 #include <errno.h>
 #include <sched.h>
 #include <pthread.h>
+#include <inttypes.h>
+
 #include "rt-utils.h"
 
 int nr_tasks;
@@ -99,6 +100,7 @@  static int done;
 static int loop;
 static int duration;
 static int quiet;
+static char outfile[MAX_PATH];
 
 static pthread_barrier_t start_barrier;
 static pthread_barrier_t end_barrier;
@@ -160,6 +162,7 @@  static void usage(int error)
 	       "-h       --help            Print this help message\n"
 	       "-l LOOPS --loops=LOOPS     Number of iterations to run (50)\n"
 	       "-m TIME  --maxerr=TIME     Max allowed error (microsecs)\n"
+	       "         --output=FILENAME write final results into FILENAME, JSON formatted\n"
 	       "-p PRIO  --prio=PRIO       base priority to start RT tasks with (2)\n"
 	       "-q       --quiet           print a summary only on exit\n"
 	       "-r TIME  --run-time=TIME   Run time (ms) to busy loop the threads (20)\n"
@@ -169,22 +172,29 @@  static void usage(int error)
 	exit(error);
 }
 
+enum option_value {
+	OPT_CHECK=1, OPT_DURATION, OPT_EQUAL, OPT_HELP, OPT_LOOPS,
+	OPT_MAXERR, OPT_OUTPUT, OPT_PRIO, OPT_QUIET, OPT_RUN_TIME,
+	OPT_SLEEP_TIME
+};
+
 static void parse_options(int argc, char *argv[])
 {
 	for (;;) {
 		int option_index = 0;
 		/** Options for getopt */
 		static struct option long_options[] = {
-			{"check",	no_argument,		NULL, 'c'},
-			{"duration",	required_argument,	NULL, 'D'},
-			{"equal",	no_argument,		NULL, 'e'},
-			{"help",	no_argument,		NULL, 'h'},
-			{"loops",	required_argument,	NULL, 'l'},
-			{"maxerr",	required_argument,	NULL, 'm'},
-			{"prio",	required_argument,	NULL, 'p'},
-			{"quiet",	no_argument,		NULL, 'q'},
-			{"run-time",	required_argument,	NULL, 'r'},
-			{"sleep-time",	required_argument,	NULL, 's'},
+			{"check",	no_argument,		NULL, OPT_CHECK},
+			{"duration",	required_argument,	NULL, OPT_DURATION},
+			{"equal",	no_argument,		NULL, OPT_EQUAL},
+			{"help",	no_argument,		NULL, OPT_HELP},
+			{"loops",	required_argument,	NULL, OPT_LOOPS},
+			{"maxerr",	required_argument,	NULL, OPT_MAXERR},
+			{"output",	required_argument,      NULL, OPT_OUTPUT },
+			{"prio",	required_argument,	NULL, OPT_PRIO},
+			{"quiet",	no_argument,		NULL, OPT_QUIET},
+			{"run-time",	required_argument,	NULL, OPT_RUN_TIME},
+			{"sleep-time",	required_argument,	NULL, OPT_SLEEP_TIME},
 			{NULL, 0, NULL, 0}
 		};
 		int c = getopt_long(argc, argv, "cD:ehl:m:p:qr:s:",
@@ -192,21 +202,50 @@  static void parse_options(int argc, char *argv[])
 		if (c == -1)
 			break;
 		switch (c) {
-		case 'c': check = 1; break;
-		case 'D': duration = parse_time_string(optarg); break;
-		case 'e': equal = 1; break;
+		case OPT_CHECK:
+		case 'c':
+			check = 1;
+			break;
+		case OPT_DURATION:
+		case 'D':
+			duration = parse_time_string(optarg);
+			break;
+		case OPT_EQUAL:
+		case 'e':
+			equal = 1;
+			break;
+		case OPT_HELP:
 		case '?':
 		case 'h':
 			usage(0);
 			break;
-		case 'l': nr_runs = atoi(optarg); break;
-		case 'm': max_err = usec2nano(atoi(optarg)); break;
-		case 'p': prio_start = atoi(optarg); break;
-		case 'q': quiet = 1; break;
+		case OPT_LOOPS:
+		case 'l':
+			nr_runs = atoi(optarg);
+			break;
+		case OPT_MAXERR:
+		case 'm':
+			max_err = usec2nano(atoi(optarg));
+			break;
+		case OPT_OUTPUT:
+			strncpy(outfile, optarg, strnlen(optarg, MAX_PATH-1));
+			break;
+		case OPT_PRIO:
+		case 'p':
+			prio_start = atoi(optarg);
+			break;
+		case OPT_QUIET:
+		case 'q':
+			quiet = 1;
+			break;
+		case OPT_RUN_TIME:
 		case 'r':
 			run_interval = atoi(optarg);
 			break;
-		case 's': interval = atoi(optarg); break;
+		case OPT_SLEEP_TIME:
+		case 's':
+			interval = atoi(optarg);
+			break;
 		default:
 			usage(1);
 		}
@@ -313,6 +352,44 @@  static void print_results(void)
 	}
 }
 
+static void write_stats(FILE *f, void *data)
+{
+	int i;
+	int t;
+	unsigned long long tasks_max[nr_tasks];
+	unsigned long long tasks_min[nr_tasks];
+	unsigned long long tasks_avg[nr_tasks];
+
+	memset(tasks_max, 0, sizeof(tasks_max[0])*nr_tasks);
+	memset(tasks_min, 0xff, sizeof(tasks_min[0])*nr_tasks);
+	memset(tasks_avg, 0, sizeof(tasks_avg[0])*nr_tasks);
+
+	for (i=0; i < nr_runs; i++) {
+		for (t=0; t < nr_tasks; t++) {
+			unsigned long long itv = intervals[i][t];
+
+			if (tasks_max[t] < itv)
+				tasks_max[t] = itv;
+			if (tasks_min[t] > itv)
+				tasks_min[t] = itv;
+			tasks_avg[t] += itv;
+		}
+	}
+
+	fprintf(f, "  \"num_threads\": %d,\n", nr_tasks);
+	fprintf(f, "  \"thread\": {\n");
+	for (i = 0; i < nr_tasks; i++) {
+		fprintf(f, "    \"%u\": {\n", i);
+		fprintf(f, "      \"prio\": %d,\n", calc_prio(i));
+		fprintf(f, "      \"min\": %lld,\n", nano2usec(tasks_min[i]));
+		fprintf(f, "      \"avg\": %lld,\n", nano2usec(tasks_avg[i]) / nr_runs);
+		fprintf(f, "      \"max\": %lld,\n", nano2usec(tasks_max[i]));
+		fprintf(f, "      \"total\": %lld\n", nano2usec(tasks_avg[i]));
+		fprintf(f, "    }%s\n", i == nr_tasks - 1 ? "" : ",");
+	}
+	fprintf(f, "  }\n");
+}
+
 static unsigned long busy_loop(unsigned long long start_time)
 {
 	unsigned long long time;
@@ -582,6 +659,9 @@  int main (int argc, char **argv)
 
 	print_results();
 
+	if (strlen(outfile) != 0)
+		rt_write_json(outfile, argc, argv, write_stats, NULL);
+
 	if (stop) {
 		/*
 		 * We use this test in bash while loops