From: Daniel Wagner <dwagner@suse.de>
To: Clark Williams <williams@redhat.com>, John Kacur <jkacur@redhat.com>
Cc: linux-rt-users@vger.kernel.org, Daniel Wagner <dwagner@suse.de>
Subject: [RFC v3 18/19] oslat: Add JSON output feature
Date: Fri, 15 Jan 2021 20:09:35 +0100 [thread overview]
Message-ID: <20210115190936.26148-19-dwagner@suse.de> (raw)
In-Reply-To: <20210115190936.26148-1-dwagner@suse.de>
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/oslat/oslat.c | 97 +++++++++++++++++++++++++++++++++++++++--------
1 file changed, 82 insertions(+), 15 deletions(-)
diff --git a/src/oslat/oslat.c b/src/oslat/oslat.c
index 9e6f70600830..5858c6c17fcf 100644
--- a/src/oslat/oslat.c
+++ b/src/oslat/oslat.c
@@ -29,7 +29,7 @@
#include <numa.h>
#include <math.h>
#include <limits.h>
-#include <linux/unistd.h>
+#include <inttypes.h>
#include <sys/prctl.h>
#include <sys/stat.h>
@@ -41,6 +41,8 @@
#include <sys/mman.h>
#include <sys/syscall.h>
+#include <linux/unistd.h>
+
#include "rt-utils.h"
#include "rt-numa.h"
#include "rt-error.h"
@@ -171,6 +173,7 @@ struct global {
uint64_t bias;
int single_preheat_thread;
int output_omit_zero_buckets;
+ char outfile[MAX_PATH];
/* Mutable state. */
volatile enum command cmd;
@@ -479,6 +482,39 @@ static void write_summary(struct thread *t)
printf("\n");
}
+static void write_summary_json(FILE *f, void *data)
+{
+ struct thread *t = data;
+ int i, j, comma;
+
+ fprintf(f, " \"num_threads\": %d,\n", g.n_threads);
+ fprintf(f, " \"thread\": {\n");
+ for (i = 0; i < g.n_threads; ++i) {
+ fprintf(f, " \"%u\": {\n", i);
+ fprintf(f, " \"cpu\": %d,\n", t[i].core_i);
+ fprintf(f, " \"freq\": %d,\n", t[i].cpu_mhz);
+ fprintf(f, " \"min\": %" PRIu64 ",\n", t[i].minlat);
+ fprintf(f, " \"avg\": %3lf,\n", t[i].average);
+ fprintf(f, " \"min\": %" PRIu64 ",\n", t[i].maxlat);
+ fprintf(f, " \"duration\": %.3f,\n",
+ cycles_to_sec(&(t[i]), t[i].runtime));
+ fprintf(f, " \"histogram\": {");
+ for (j = 0, comma = 0; j < g.bucket_size; j++) {
+ if (t[i].buckets[j] == 0)
+ continue;
+ fprintf(f, "%s", comma ? ",\n" : "\n");
+ fprintf(f, " \"%" PRIu64 "\": %" PRIu64,
+ g.bias+j+1, t[i].buckets[j]);
+ comma = 1;
+ }
+ if (comma)
+ fprintf(f, "\n");
+ fprintf(f, " },\n");
+ fprintf(f, " }%s\n", i == g.n_threads - 1 ? "" : ",");
+ }
+ fprintf(f, " }\n");
+}
+
static void run_expt(struct thread *threads, int runtime_secs)
{
int i;
@@ -533,6 +569,7 @@ static void usage(int error)
" NOTE: please make sure the CPU frequency on all testing cores\n"
" are locked before using this parmater. If you don't know how\n"
" to lock the freq then please don't use this parameter.\n"
+ " --output=FILENAME write final results into FILENAME, JSON formatted\n"
"-T, --trace-threshold Stop the test when threshold triggered (in us),\n"
" print a marker in ftrace and stop ftrace too.\n"
"-v, --version Display the version of the software.\n"
@@ -557,34 +594,45 @@ static int workload_select(char *name)
return -1;
}
+enum option_value {
+ OPT_BUCKETSIZE=1, OPT_CPU_LIST, OPT_CPU_MAIN_THREAD,
+ OPT_DURATION, OPT_RT_PRIO, OPT_HELP, OPT_TRACE_TH,
+ OPT_WORKLOAD, OPT_WORKLOAD_MEM, OPT_BIAS, OPT_OUTPUT,
+ OPT_SINGLE_PREHEAT, OPT_ZERO_OMIT, OPT_VERSION
+
+};
+
/* Process commandline options */
static void parse_options(int argc, char *argv[])
{
while (1) {
+ int option_index = 0;
static struct option options[] = {
- { "bucket-size", required_argument, NULL, 'b' },
- { "cpu-list", required_argument, NULL, 'c' },
- { "cpu-main-thread", required_argument, NULL, 'C'},
- { "duration", required_argument, NULL, 'D' },
- { "rtprio", required_argument, NULL, 'f' },
- { "help", no_argument, NULL, 'h' },
- { "trace-threshold", required_argument, NULL, 'T' },
- { "workload", required_argument, NULL, 'w'},
- { "workload-mem", required_argument, NULL, 'm'},
- { "bias", no_argument, NULL, 'B'},
- { "single-preheat", no_argument, NULL, 's'},
- { "zero-omit", no_argument, NULL, 'u'},
- { "version", no_argument, NULL, 'v'},
+ { "bucket-size",required_argument, NULL, OPT_BUCKETSIZE },
+ { "cpu-list", required_argument, NULL, OPT_CPU_LIST },
+ { "cpu-main-thread", required_argument, NULL, OPT_CPU_MAIN_THREAD},
+ { "duration", required_argument, NULL, OPT_DURATION },
+ { "rtprio", required_argument, NULL, OPT_RT_PRIO },
+ { "help", no_argument, NULL, OPT_HELP },
+ { "trace-threshold", required_argument, NULL, OPT_TRACE_TH },
+ { "workload", required_argument, NULL, OPT_WORKLOAD },
+ { "workload-mem", required_argument, NULL, OPT_WORKLOAD_MEM },
+ { "bias", no_argument, NULL, OPT_BIAS },
+ { "single-preheat", no_argument, NULL, OPT_SINGLE_PREHEAT },
+ { "output", required_argument, NULL, OPT_OUTPUT },
+ { "zero-omit", no_argument, NULL, OPT_ZERO_OMIT },
+ { "version", no_argument, NULL, OPT_VERSION },
{ NULL, 0, NULL, 0 },
};
int i, c = getopt_long(argc, argv, "b:Bc:C:D:f:hm:sw:T:vz",
- options, NULL);
+ options, &option_index);
long ncores;
if (c == -1)
break;
switch (c) {
+ case OPT_BUCKETSIZE:
case 'b':
g.bucket_size = strtol(optarg, NULL, 10);
if (g.bucket_size > 1024 || g.bucket_size <= 4) {
@@ -593,12 +641,15 @@ static void parse_options(int argc, char *argv[])
exit(1);
}
break;
+ case OPT_BIAS:
case 'B':
g.enable_bias = 1;
break;
+ case OPT_CPU_LIST:
case 'c':
g.cpu_list = strdup(optarg);
break;
+ case OPT_CPU_MAIN_THREAD:
case 'C':
ncores = sysconf(_SC_NPROCESSORS_CONF);
g.cpu_main_thread = strtol(optarg, NULL, 10);
@@ -608,6 +659,7 @@ static void parse_options(int argc, char *argv[])
exit(1);
}
break;
+ case OPT_DURATION:
case 'D':
g.runtime = parse_time_string(optarg);
if (!g.runtime) {
@@ -615,6 +667,7 @@ static void parse_options(int argc, char *argv[])
exit(1);
}
break;
+ case OPT_RT_PRIO:
case 'f':
g.rtprio = strtol(optarg, NULL, 10);
if (g.rtprio < 1 || g.rtprio > 99) {
@@ -622,6 +675,10 @@ static void parse_options(int argc, char *argv[])
exit(1);
}
break;
+ case OPT_OUTPUT:
+ strncpy(g.outfile, optarg, strnlen(optarg, MAX_PATH-1));
+ break;
+ case OPT_TRACE_TH:
case 'T':
g.trace_threshold = strtol(optarg, NULL, 10);
if (g.trace_threshold <= 0) {
@@ -630,6 +687,7 @@ static void parse_options(int argc, char *argv[])
}
enable_trace_mark();
break;
+ case OPT_WORKLOAD:
case 'w':
if (workload_select(optarg)) {
printf("Unknown workload '%s'. Please choose from: ", optarg);
@@ -642,12 +700,14 @@ static void parse_options(int argc, char *argv[])
exit(1);
}
break;
+ case OPT_WORKLOAD_MEM:
case 'm':
if (parse_mem_string(optarg, &g.workload_mem_size)) {
printf("Unknown workload memory size '%s'.\n\n", optarg);
exit(1);
}
break;
+ case OPT_SINGLE_PREHEAT:
case 's':
/*
* Only use one core for pre-heat. Then if --bias is used, the
@@ -655,6 +715,7 @@ static void parse_options(int argc, char *argv[])
*/
g.single_preheat_thread = true;
break;
+ case OPT_VERSION:
case 'v':
/*
* Because we always dump the version even before parsing options,
@@ -662,9 +723,11 @@ static void parse_options(int argc, char *argv[])
*/
exit(0);
break;
+ case OPT_ZERO_OMIT:
case 'z':
g.output_omit_zero_buckets = 1;
break;
+ case OPT_HELP:
case 'h':
usage(0);
break;
@@ -781,6 +844,10 @@ int main(int argc, char *argv[])
write_summary(threads);
+ if (strlen(g.outfile) != 0)
+ rt_write_json(g.outfile, argc, argv,
+ write_summary_json, threads);
+
if (g.cpu_list) {
free(g.cpu_list);
g.cpu_list = NULL;
--
2.29.2
next prev parent reply other threads:[~2021-01-15 19:11 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-01-15 19:09 [RFC v3 00/19] Generate machine-readable output Daniel Wagner
2021-01-15 19:09 ` [RFC v3 01/19] pip_stress: De-constify prio_min Daniel Wagner
2021-01-26 6:06 ` John Kacur
2021-01-15 19:09 ` [RFC v3 02/19] ptsematest: Return correct exit code when showing help Daniel Wagner
2021-01-26 6:09 ` John Kacur
2021-01-15 19:09 ` [RFC v3 03/19] rt-tests: Rename error.h to rt-error.h Daniel Wagner
2021-01-26 6:12 ` John Kacur
2021-01-15 19:09 ` [RFC v3 04/19] cyclictest: Move thread data to struct thread_param Daniel Wagner
2021-01-15 19:09 ` [RFC v3 05/19] cyclictest: Remove libnuma API version 1 support Daniel Wagner
2021-01-26 6:15 ` John Kacur
2021-01-15 19:09 ` [RFC v3 06/19] signaltest: Move thread data to struct thread_param Daniel Wagner
2021-01-15 19:09 ` [RFC v3 07/19] cyclicdeadline: Add missing step command line argument Daniel Wagner
2021-01-26 6:19 ` John Kacur
2021-01-15 19:09 ` [RFC v3 08/19] cyclicdeadline: Remove unused struct thread_param Daniel Wagner
2021-01-26 6:22 ` John Kacur
2021-01-15 19:09 ` [RFC v3 09/19] cyclicdeadline: Remove unused members in struct thread_stat Daniel Wagner
2021-01-15 19:09 ` [RFC v3 10/19] rt-utils: Add JSON common header output helper Daniel Wagner
2021-01-15 19:09 ` [RFC v3 11/19] cyclictest: Add JSON output feature Daniel Wagner
2021-01-15 19:09 ` [RFC v3 12/19] signaltest: " Daniel Wagner
2021-01-15 19:09 ` [RFC v3 13/19] cyclicdeadline: " Daniel Wagner
2021-01-15 19:09 ` [RFC v3 14/19] pmqtest: " Daniel Wagner
2021-01-15 19:09 ` [RFC v3 15/19] ptsematest: " Daniel Wagner
2021-01-15 19:09 ` [RFC v3 16/19] sigwaittest: " Daniel Wagner
2021-01-15 19:09 ` [RFC v3 17/19] svsematest: " Daniel Wagner
2021-01-15 19:09 ` Daniel Wagner [this message]
2021-01-15 19:09 ` [RFC v3 19/19] rt-migrate-test: " Daniel Wagner
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210115190936.26148-19-dwagner@suse.de \
--to=dwagner@suse.de \
--cc=jkacur@redhat.com \
--cc=linux-rt-users@vger.kernel.org \
--cc=williams@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).