All of lore.kernel.org
 help / color / mirror / Atom feed
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

  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.