From: John Kacur <jkacur@redhat.com>
To: Daniel Wagner <dwagner@suse.de>
Cc: Clark Williams <williams@redhat.com>, linux-rt-users@vger.kernel.org
Subject: Re: [rt-tests v4 11/12] oslat: Add JSON output feature
Date: Tue, 26 Jan 2021 11:35:36 -0500 (EST) [thread overview]
Message-ID: <b12e3868-e2d4-cb84-d024-27dda1931fd2@redhat.com> (raw)
In-Reply-To: <20210126091946.1241-12-dwagner@suse.de>
On Tue, 26 Jan 2021, Daniel Wagner wrote:
> 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.30.0
>
>
I haven't looked at the implementation of JSON yet, but I am excited about
this feature, looking forward to it. Please finish the numa changes
and other clean-ups first though.
Thanks
John
next prev parent reply other threads:[~2021-01-26 17:21 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-01-26 9:19 [rt-tests v4 00/12] Generate machine-readable output Daniel Wagner
2021-01-26 9:19 ` [rt-tests v4 01/12] cyclictest: Move thread data to struct thread_param Daniel Wagner
2021-01-26 9:19 ` [rt-tests v4 02/12] signaltest: " Daniel Wagner
2021-01-26 9:19 ` [rt-tests v4 03/12] rt-utils: Add JSON common header output helper Daniel Wagner
2021-01-26 9:19 ` [rt-tests v4 04/12] cyclictest: Add JSON output feature Daniel Wagner
2021-01-26 9:19 ` [rt-tests v4 05/12] signaltest: " Daniel Wagner
2021-01-26 9:19 ` [rt-tests v4 06/12] cyclicdeadline: " Daniel Wagner
2021-01-26 9:19 ` [rt-tests v4 07/12] pmqtest: " Daniel Wagner
2021-01-26 9:19 ` [rt-tests v4 08/12] ptsematest: " Daniel Wagner
2021-01-26 9:19 ` [rt-tests v4 09/12] sigwaittest: " Daniel Wagner
2021-01-26 9:19 ` [rt-tests v4 10/12] svsematest: " Daniel Wagner
2021-01-26 9:19 ` [rt-tests v4 11/12] oslat: " Daniel Wagner
2021-01-26 16:35 ` John Kacur [this message]
2021-01-26 9:19 ` [rt-tests v4 12/12] rt-migrate-test: " Daniel Wagner
2021-01-26 11:01 ` [rt-tests v4 00/12] Generate machine-readable output Ahmed S. Darwish
2021-01-26 12:32 ` 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=b12e3868-e2d4-cb84-d024-27dda1931fd2@redhat.com \
--to=jkacur@redhat.com \
--cc=dwagner@suse.de \
--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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.