This patch series add general benchmark subcommand to perf.
The subcommand will unify the benchmarking programs
and provide these in standardized way.
I fixed this series for latest tip tree.
My previous patch series conflicts with cmd_probe().
So please discard v4 and use this v5.
Hitoshi Mitake (7):
Adding new directory and header for new subcommand 'bench'
sched-messaging.c: benchmark for scheduler and IPC mechanisms based
on hackbench
sched-pipe.c: benchmark for pipe() system call
builtin-bench.c: General framework for benchmark suites
Modifying builtin.h for new prototype
Modyfing perf.c for subcommand 'bench'
Modyfing Makefile to build subcommand 'bench'
tools/perf/Makefile | 6 +
tools/perf/bench/bench.h | 9 +
tools/perf/bench/sched-messaging.c | 332 ++++++++++++++++++++++++++++++++++++
tools/perf/bench/sched-pipe.c | 113 ++++++++++++
tools/perf/builtin-bench.c | 128 ++++++++++++++
tools/perf/builtin.h | 1 +
tools/perf/perf.c | 1 +
7 files changed, 590 insertions(+), 0 deletions(-)
create mode 100644 tools/perf/bench/bench.h
create mode 100644 tools/perf/bench/sched-messaging.c
create mode 100644 tools/perf/bench/sched-pipe.c
create mode 100644 tools/perf/builtin-bench.c
This patch adds bench/ directory and bench/bench.h.
bench/ directory will contain modules for bench subcommand.
bench/bench.h is for listing prototypes of module functions.
Signed-off-by: Hitoshi Mitake <[email protected]>
Cc: Rusty Russell <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Mike Galbraith <[email protected]>
---
tools/perf/bench/bench.h | 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)
create mode 100644 tools/perf/bench/bench.h
diff --git a/tools/perf/bench/bench.h b/tools/perf/bench/bench.h
new file mode 100644
index 0000000..59adb27
--- /dev/null
+++ b/tools/perf/bench/bench.h
@@ -0,0 +1,9 @@
+#ifndef BENCH_H
+#define BENCH_H
+
+extern int bench_sched_messaging(int argc, const char **argv,
+ const char *prefix);
+extern int bench_sched_pipe(int argc, const char **argv,
+ const char *prefix);
+
+#endif
--
1.6.5.2
This patch adds bench/sched-messaging.c.
This benchmark measures performance of scheduler and IPC mechanisms,
and is based on hackbench by Rusty Russell.
Example of usage:
% perf bench sched messaging -g 20 -l 1000 -s
5.432 # in sec
% perf bench sched messaging # run with default options
(20 sender and receiver processes per group)
(10 groups == 400 processes run)
Total time:0.308 sec
% perf bench sched messaging -t -g 20 # # be multi-thread, with 20 groups
(20 sender and receiver threads per group)
(20 groups == 800 threads run)
Total time:0.582 sec
Signed-off-by: Hitoshi Mitake <[email protected]>
Cc: Rusty Russell <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Mike Galbraith <[email protected]>
---
tools/perf/bench/sched-messaging.c | 332 ++++++++++++++++++++++++++++++++++++
1 files changed, 332 insertions(+), 0 deletions(-)
create mode 100644 tools/perf/bench/sched-messaging.c
diff --git a/tools/perf/bench/sched-messaging.c b/tools/perf/bench/sched-messaging.c
new file mode 100644
index 0000000..36b62c5
--- /dev/null
+++ b/tools/perf/bench/sched-messaging.c
@@ -0,0 +1,332 @@
+/*
+ *
+ * builtin-bench-messaging.c
+ *
+ * messaging: Benchmark for scheduler and IPC mechanisms
+ *
+ * Based on hackbench by Rusty Russell <[email protected]>
+ * Ported to perf by Hitoshi Mitake <[email protected]>
+ *
+ */
+
+#include "../perf.h"
+#include "../util/util.h"
+#include "../util/parse-options.h"
+#include "../builtin.h"
+#include "bench.h"
+
+/* Test groups of 20 processes spraying to 20 receivers */
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <sys/poll.h>
+#include <limits.h>
+
+#define DATASIZE 100
+
+static int use_pipes = 0;
+static unsigned int loops = 100;
+static unsigned int thread_mode = 0;
+static unsigned int num_groups = 10;
+static int simple = 0;
+
+struct sender_context {
+ unsigned int num_fds;
+ int ready_out;
+ int wakefd;
+ int out_fds[0];
+};
+
+struct receiver_context {
+ unsigned int num_packets;
+ int in_fds[2];
+ int ready_out;
+ int wakefd;
+};
+
+static void barf(const char *msg)
+{
+ fprintf(stderr, "%s (error: %s)\n", msg, strerror(errno));
+ exit(1);
+}
+
+static void fdpair(int fds[2])
+{
+ if (use_pipes) {
+ if (pipe(fds) == 0)
+ return;
+ } else {
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == 0)
+ return;
+ }
+
+ barf(use_pipes ? "pipe()" : "socketpair()");
+}
+
+/* Block until we're ready to go */
+static void ready(int ready_out, int wakefd)
+{
+ char dummy;
+ struct pollfd pollfd = { .fd = wakefd, .events = POLLIN };
+
+ /* Tell them we're ready. */
+ if (write(ready_out, &dummy, 1) != 1)
+ barf("CLIENT: ready write");
+
+ /* Wait for "GO" signal */
+ if (poll(&pollfd, 1, -1) != 1)
+ barf("poll");
+}
+
+/* Sender sprays loops messages down each file descriptor */
+static void *sender(struct sender_context *ctx)
+{
+ char data[DATASIZE];
+ unsigned int i, j;
+
+ ready(ctx->ready_out, ctx->wakefd);
+
+ /* Now pump to every receiver. */
+ for (i = 0; i < loops; i++) {
+ for (j = 0; j < ctx->num_fds; j++) {
+ int ret, done = 0;
+
+again:
+ ret = write(ctx->out_fds[j], data + done,
+ sizeof(data)-done);
+ if (ret < 0)
+ barf("SENDER: write");
+ done += ret;
+ if (done < DATASIZE)
+ goto again;
+ }
+ }
+
+ return NULL;
+}
+
+
+/* One receiver per fd */
+static void *receiver(struct receiver_context* ctx)
+{
+ unsigned int i;
+
+ if (!thread_mode)
+ close(ctx->in_fds[1]);
+
+ /* Wait for start... */
+ ready(ctx->ready_out, ctx->wakefd);
+
+ /* Receive them all */
+ for (i = 0; i < ctx->num_packets; i++) {
+ char data[DATASIZE];
+ int ret, done = 0;
+
+again:
+ ret = read(ctx->in_fds[0], data + done, DATASIZE - done);
+ if (ret < 0)
+ barf("SERVER: read");
+ done += ret;
+ if (done < DATASIZE)
+ goto again;
+ }
+
+ return NULL;
+}
+
+static pthread_t create_worker(void *ctx, void *(*func)(void *))
+{
+ pthread_attr_t attr;
+ pthread_t childid;
+ int err;
+
+ if (!thread_mode) {
+ /* process mode */
+ /* Fork the receiver. */
+ switch (fork()) {
+ case -1:
+ barf("fork()");
+ break;
+ case 0:
+ (*func) (ctx);
+ exit(0);
+ break;
+ default:
+ break;
+ }
+
+ return (pthread_t)0;
+ }
+
+ if (pthread_attr_init(&attr) != 0)
+ barf("pthread_attr_init:");
+
+#ifndef __ia64__
+ if (pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN) != 0)
+ barf("pthread_attr_setstacksize");
+#endif
+
+ err = pthread_create(&childid, &attr, func, ctx);
+ if (err != 0) {
+ fprintf(stderr, "pthread_create failed: %s (%d)\n",
+ strerror(err), err);
+ exit(-1);
+ }
+ return childid;
+}
+
+static void reap_worker(pthread_t id)
+{
+ int proc_status;
+ void *thread_status;
+
+ if (!thread_mode) {
+ /* process mode */
+ wait(&proc_status);
+ if (!WIFEXITED(proc_status))
+ exit(1);
+ } else {
+ pthread_join(id, &thread_status);
+ }
+}
+
+/* One group of senders and receivers */
+static unsigned int group(pthread_t *pth,
+ unsigned int num_fds,
+ int ready_out,
+ int wakefd)
+{
+ unsigned int i;
+ struct sender_context *snd_ctx = malloc(sizeof(struct sender_context)
+ + num_fds * sizeof(int));
+
+ if (!snd_ctx)
+ barf("malloc()");
+
+ for (i = 0; i < num_fds; i++) {
+ int fds[2];
+ struct receiver_context *ctx = malloc(sizeof(*ctx));
+
+ if (!ctx)
+ barf("malloc()");
+
+
+ /* Create the pipe between client and server */
+ fdpair(fds);
+
+ ctx->num_packets = num_fds * loops;
+ ctx->in_fds[0] = fds[0];
+ ctx->in_fds[1] = fds[1];
+ ctx->ready_out = ready_out;
+ ctx->wakefd = wakefd;
+
+ pth[i] = create_worker(ctx, (void *)receiver);
+
+ snd_ctx->out_fds[i] = fds[1];
+ if (!thread_mode)
+ close(fds[0]);
+ }
+
+ /* Now we have all the fds, fork the senders */
+ for (i = 0; i < num_fds; i++) {
+ snd_ctx->ready_out = ready_out;
+ snd_ctx->wakefd = wakefd;
+ snd_ctx->num_fds = num_fds;
+
+ pth[num_fds+i] = create_worker(snd_ctx, (void *)sender);
+ }
+
+ /* Close the fds we have left */
+ if (!thread_mode)
+ for (i = 0; i < num_fds; i++)
+ close(snd_ctx->out_fds[i]);
+
+ /* Return number of children to reap */
+ return num_fds * 2;
+}
+
+static const struct option options[] = {
+ OPT_BOOLEAN('p', "pipe", &use_pipes,
+ "Use pipe() instead of socketpair()"),
+ OPT_BOOLEAN('t', "thread", &thread_mode,
+ "Be multi thread instead of multi process"),
+ OPT_INTEGER('g', "group", &num_groups,
+ "Specify number of groups"),
+ OPT_INTEGER('l', "loop", &loops,
+ "Specify number of loops"),
+ OPT_BOOLEAN('s', "simple-output", &simple,
+ "Do simple output (this maybe useful for"
+ "processing by scripts or graph tools like gnuplot)"),
+ OPT_END()
+};
+
+static const char * const bench_sched_message_usage[] = {
+ "perf bench sched messaging <options>",
+ NULL
+};
+
+int bench_sched_messaging(int argc, const char **argv,
+ const char *prefix __used)
+{
+ unsigned int i, total_children;
+ struct timeval start, stop, diff;
+ unsigned int num_fds = 20;
+ int readyfds[2], wakefds[2];
+ char dummy;
+ pthread_t *pth_tab;
+
+ argc = parse_options(argc, argv, options,
+ bench_sched_message_usage, 0);
+
+ pth_tab = malloc(num_fds * 2 * num_groups * sizeof(pthread_t));
+ if (!pth_tab)
+ barf("main:malloc()");
+
+ fdpair(readyfds);
+ fdpair(wakefds);
+
+ total_children = 0;
+ for (i = 0; i < num_groups; i++)
+ total_children += group(pth_tab+total_children, num_fds,
+ readyfds[1], wakefds[0]);
+
+ /* Wait for everyone to be ready */
+ for (i = 0; i < total_children; i++)
+ if (read(readyfds[0], &dummy, 1) != 1)
+ barf("Reading for readyfds");
+
+ gettimeofday(&start, NULL);
+
+ /* Kick them off */
+ if (write(wakefds[1], &dummy, 1) != 1)
+ barf("Writing to start them");
+
+ /* Reap them all */
+ for (i = 0; i < total_children; i++)
+ reap_worker(pth_tab[i]);
+
+ gettimeofday(&stop, NULL);
+
+ timersub(&stop, &start, &diff);
+
+ if (simple)
+ printf("%lu.%03lu\n", diff.tv_sec, diff.tv_usec/1000);
+ else {
+ printf("(%d sender and receiver %s per group)\n",
+ num_fds, thread_mode ? "threads" : "processes");
+ printf("(%d groups == %d %s run)\n\n",
+ num_groups, num_groups * 2 * num_fds,
+ thread_mode ? "threads" : "processes");
+ printf("\tTotal time:%lu.%03lu sec\n",
+ diff.tv_sec, diff.tv_usec/1000);
+ }
+
+ return 0;
+}
--
1.6.5.2
This patch adds bench/sched-pipe.c.
bench/sched-pipe.c is a benchmark program
to measure performance of pipe() system call.
This benchmark is based on pipe-test-1m.c by Ingo Molnar.
http://people.redhat.com/mingo/cfs-scheduler/tools/pipe-test-1m.c
Example of use:
% perf bench sched pipe
(executing 1000000 pipe operations between two tasks)
Total time:4.499 sec
4.499179 usecs/op
222262 ops/sec
% perf bench sched pipe -s -l 1000
0.015
Signed-off-by: Hitoshi Mitake <[email protected]>
Cc: Rusty Russell <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Mike Galbraith <[email protected]>
---
tools/perf/bench/sched-pipe.c | 113 +++++++++++++++++++++++++++++++++++++++++
1 files changed, 113 insertions(+), 0 deletions(-)
create mode 100644 tools/perf/bench/sched-pipe.c
diff --git a/tools/perf/bench/sched-pipe.c b/tools/perf/bench/sched-pipe.c
new file mode 100644
index 0000000..3214ed2
--- /dev/null
+++ b/tools/perf/bench/sched-pipe.c
@@ -0,0 +1,113 @@
+/*
+ *
+ * builtin-bench-pipe.c
+ *
+ * pipe: Benchmark for pipe()
+ *
+ * Based on pipe-test-1m.c by Ingo Molnar <[email protected]>
+ * http://people.redhat.com/mingo/cfs-scheduler/tools/pipe-test-1m.c
+ * Ported to perf by Hitoshi Mitake <[email protected]>
+ *
+ */
+
+#include "../perf.h"
+#include "../util/util.h"
+#include "../util/parse-options.h"
+#include "../builtin.h"
+#include "bench.h"
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <linux/unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <sys/time.h>
+
+#define LOOPS_DEFAULT 1000000
+static int loops = LOOPS_DEFAULT;
+static int simple = 0;
+
+static const struct option options[] = {
+ OPT_INTEGER('l', "loop", &loops,
+ "Specify number of loops"),
+ OPT_BOOLEAN('s', "simple-output", &simple,
+ "Do simple output (this maybe useful for"
+ "processing by scripts or graph tools like gnuplot)"),
+ OPT_END()
+};
+
+static const char * const bench_sched_pipe_usage[] = {
+ "perf bench sched pipe <options>",
+ NULL
+};
+
+int bench_sched_pipe(int argc, const char **argv,
+ const char *prefix __used)
+{
+ int pipe_1[2], pipe_2[2];
+ int m = 0, i;
+ struct timeval start, stop, diff;
+ unsigned long long result_usec = 0;
+
+ /*
+ * why does "ret" exist?
+ * discarding returned value of read(), write()
+ * causes error in building environment for perf
+ */
+ int ret;
+ pid_t pid;
+
+ argc = parse_options(argc, argv, options,
+ bench_sched_pipe_usage, 0);
+
+ assert(!pipe(pipe_1));
+ assert(!pipe(pipe_2));
+
+ pid = fork();
+ assert(pid >= 0);
+
+ gettimeofday(&start, NULL);
+
+ if (!pid) {
+ for (i = 0; i < loops; i++) {
+ ret = read(pipe_1[0], &m, sizeof(int));
+ ret = write(pipe_2[1], &m, sizeof(int));
+ }
+ } else {
+ for (i = 0; i < loops; i++) {
+ ret = write(pipe_1[1], &m, sizeof(int));
+ ret = read(pipe_2[0], &m, sizeof(int));
+ }
+ }
+
+ gettimeofday(&stop, NULL);
+ timersub(&stop, &start, &diff);
+
+ if (pid)
+ return 0;
+
+ if (simple)
+ printf("%lu.%03lu\n",
+ diff.tv_sec, diff.tv_usec / 1000);
+ else {
+ printf("(executing %d pipe operations between two tasks)\n\n",
+ loops);
+
+ result_usec = diff.tv_sec * 1000000;
+ result_usec += diff.tv_usec;
+
+ printf("\tTotal time:%lu.%03lu sec\n",
+ diff.tv_sec, diff.tv_usec / 1000);
+ printf("\t\t%lf usecs/op\n",
+ (double)result_usec / (double)loops);
+ printf("\t\t%d ops/sec\n",
+ (int)((double)loops /
+ ((double)result_usec / (double)1000000)));
+ }
+
+ return 0;
+}
--
1.6.5.2
This patch adds builtin-bench.c
builtin-bench.c is a general framework for benchmark suites.
Signed-off-by: Hitoshi Mitake <[email protected]>
Cc: Rusty Russell <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Mike Galbraith <[email protected]>
---
tools/perf/builtin-bench.c | 128 ++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 128 insertions(+), 0 deletions(-)
create mode 100644 tools/perf/builtin-bench.c
diff --git a/tools/perf/builtin-bench.c b/tools/perf/builtin-bench.c
new file mode 100644
index 0000000..31f4164
--- /dev/null
+++ b/tools/perf/builtin-bench.c
@@ -0,0 +1,128 @@
+/*
+ *
+ * builtin-bench.c
+ *
+ * General benchmarking subsystem provided by perf
+ *
+ * Copyright (C) 2009, Hitoshi Mitake <[email protected]>
+ *
+ */
+
+/*
+ *
+ * Available subsystem list:
+ * sched ... scheduler and IPC mechanism
+ *
+ */
+
+#include "perf.h"
+#include "util/util.h"
+#include "util/parse-options.h"
+#include "builtin.h"
+#include "bench/bench.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct bench_suite {
+ const char *name;
+ const char *summary;
+ int (*fn)(int, const char **, const char *);
+};
+
+static struct bench_suite sched_suites[] = {
+ { "messaging",
+ "Benchmark for scheduler and IPC mechanisms",
+ bench_sched_messaging },
+ { "pipe",
+ "Flood of communication over pipe() between two processes",
+ bench_sched_pipe },
+ { NULL,
+ NULL,
+ NULL }
+};
+
+struct bench_subsys {
+ const char *name;
+ const char *summary;
+ struct bench_suite *suites;
+};
+
+static struct bench_subsys subsystems[] = {
+ { "sched",
+ "scheduler and IPC mechanism",
+ sched_suites },
+ { NULL,
+ NULL,
+ NULL }
+};
+
+static void dump_suites(int subsys_index)
+{
+ int i;
+
+ printf("List of available suites for %s...\n\n",
+ subsystems[subsys_index].name);
+
+ for (i = 0; subsystems[subsys_index].suites[i].name; i++)
+ printf("\t%s: %s\n",
+ subsystems[subsys_index].suites[i].name,
+ subsystems[subsys_index].suites[i].summary);
+
+ printf("\n");
+ return;
+}
+
+int cmd_bench(int argc, const char **argv, const char *prefix __used)
+{
+ int i, j, status = 0;
+
+ if (argc < 2) {
+ /* No subsystem specified. */
+ printf("Usage: perf bench <subsystem> <suite> [<options>]\n\n");
+ printf("List of available subsystems...\n\n");
+
+ for (i = 0; subsystems[i].name; i++)
+ printf("\t%s: %s\n",
+ subsystems[i].name, subsystems[i].summary);
+ printf("\n");
+
+ goto end;
+ }
+
+ for (i = 0; subsystems[i].name; i++) {
+ if (strcmp(subsystems[i].name, argv[1]))
+ continue;
+
+ if (argc < 3) {
+ /* No suite specified. */
+ dump_suites(i);
+ goto end;
+ }
+
+ for (j = 0; subsystems[i].suites[j].name; j++) {
+ if (strcmp(subsystems[i].suites[j].name, argv[2]))
+ continue;
+
+ status = subsystems[i].suites[j].fn(argc - 2,
+ argv + 2, prefix);
+ goto end;
+ }
+
+ if (!strcmp(argv[2], "-h") || !strcmp(argv[2], "--help")) {
+ dump_suites(i);
+ goto end;
+ }
+
+ printf("Unknown suite:%s for %s\n", argv[2], argv[1]);
+ status = 1;
+ goto end;
+ }
+
+ printf("Unknown subsystem:%s\n", argv[1]);
+ status = 1;
+
+end:
+ return status;
+}
--
1.6.5.2
This patch modifies builtin.h to add prototype of cmd_bench().
Signed-off-by: Hitoshi Mitake <[email protected]>
Cc: Rusty Russell <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Mike Galbraith <[email protected]>
---
tools/perf/builtin.h | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h
index ad5f0f4..e84f63e 100644
--- a/tools/perf/builtin.h
+++ b/tools/perf/builtin.h
@@ -26,5 +26,6 @@ extern int cmd_top(int argc, const char **argv, const char *prefix);
extern int cmd_trace(int argc, const char **argv, const char *prefix);
extern int cmd_version(int argc, const char **argv, const char *prefix);
extern int cmd_probe(int argc, const char **argv, const char *prefix);
+extern int cmd_bench(int argc, const char **argv, const char *prefix);
#endif
--
1.6.5.2
This patch modifies perf.c for invoking 'bench' subcommand.
Signed-off-by: Hitoshi Mitake <[email protected]>
Cc: Rusty Russell <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Mike Galbraith <[email protected]>
---
tools/perf/perf.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 9cafe54..5877b01 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -296,6 +296,7 @@ static void handle_internal_command(int argc, const char **argv)
{ "trace", cmd_trace, 0 },
{ "sched", cmd_sched, 0 },
{ "probe", cmd_probe, 0 },
+ { "bench", cmd_bench, 0 },
};
unsigned int i;
static const char ext[] = STRIP_EXTENSION;
--
1.6.5.2
This patch modifies Makefile for new files related to 'bench' subcommand.
Signed-off-by: Hitoshi Mitake <[email protected]>
Cc: Rusty Russell <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Mike Galbraith <[email protected]>
---
tools/perf/Makefile | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index a130134..17f8e9d 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -427,6 +427,12 @@ BUILTIN_OBJS += builtin-timechart.o
BUILTIN_OBJS += builtin-top.o
BUILTIN_OBJS += builtin-trace.o
BUILTIN_OBJS += builtin-probe.o
+BUILTIN_OBJS += builtin-bench.o
+
+# Benchmark modules
+BUILTIN_OBJS += bench/sched-messaging.o
+BUILTIN_OBJS += bench/sched-pipe.o
+
PERFLIBS = $(LIB_FILE)
--
1.6.5.2
* Hitoshi Mitake <[email protected]> wrote:
> This patch series add general benchmark subcommand to perf.
>
> The subcommand will unify the benchmarking programs
> and provide these in standardized way.
>
> I fixed this series for latest tip tree.
> My previous patch series conflicts with cmd_probe().
> So please discard v4 and use this v5.
>
> Hitoshi Mitake (7):
> Adding new directory and header for new subcommand 'bench'
> sched-messaging.c: benchmark for scheduler and IPC mechanisms based
> on hackbench
> sched-pipe.c: benchmark for pipe() system call
> builtin-bench.c: General framework for benchmark suites
> Modifying builtin.h for new prototype
> Modyfing perf.c for subcommand 'bench'
> Modyfing Makefile to build subcommand 'bench'
>
> tools/perf/Makefile | 6 +
> tools/perf/bench/bench.h | 9 +
> tools/perf/bench/sched-messaging.c | 332 ++++++++++++++++++++++++++++++++++++
> tools/perf/bench/sched-pipe.c | 113 ++++++++++++
> tools/perf/builtin-bench.c | 128 ++++++++++++++
> tools/perf/builtin.h | 1 +
> tools/perf/perf.c | 1 +
> 7 files changed, 590 insertions(+), 0 deletions(-)
> create mode 100644 tools/perf/bench/bench.h
> create mode 100644 tools/perf/bench/sched-messaging.c
> create mode 100644 tools/perf/bench/sched-pipe.c
> create mode 100644 tools/perf/builtin-bench.c
Looks good - i've applied the patches to tip:perf/bench, thanks!
There's one small bug i noticed:
$ ./perf bench sched pipe
(executing 1000000 pipe operations between two tasks)
Total time:4.898 sec
$ 4.898586 usecs/op
204140 ops/sec
the shell prompt came back before the usecs/op and ops/sec line was
printed. Process teardown race, lack of wait() or so?
Ingo
Commit-ID: c426bba069e65ea438880a04aa4e7c5b880e1728
Gitweb: http://git.kernel.org/tip/c426bba069e65ea438880a04aa4e7c5b880e1728
Author: Hitoshi Mitake <[email protected]>
AuthorDate: Thu, 5 Nov 2009 09:31:31 +0900
Committer: Ingo Molnar <[email protected]>
CommitDate: Sun, 8 Nov 2009 10:19:15 +0100
perf bench: Add new directory and header for new subcommand 'bench'
This patch adds bench/ directory and bench/bench.h.
bench/ directory will contain modules for bench subcommand.
bench/bench.h is for listing prototypes of module functions.
Signed-off-by: Hitoshi Mitake <[email protected]>
Cc: Rusty Russell <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: [email protected]
Cc: Jiri Kosina <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>
---
tools/perf/bench/bench.h | 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/tools/perf/bench/bench.h b/tools/perf/bench/bench.h
new file mode 100644
index 0000000..59adb27
--- /dev/null
+++ b/tools/perf/bench/bench.h
@@ -0,0 +1,9 @@
+#ifndef BENCH_H
+#define BENCH_H
+
+extern int bench_sched_messaging(int argc, const char **argv,
+ const char *prefix);
+extern int bench_sched_pipe(int argc, const char **argv,
+ const char *prefix);
+
+#endif
Commit-ID: e27454cc6352c4226ddc76f5e3a5dedd7dff456a
Gitweb: http://git.kernel.org/tip/e27454cc6352c4226ddc76f5e3a5dedd7dff456a
Author: Hitoshi Mitake <[email protected]>
AuthorDate: Thu, 5 Nov 2009 09:31:32 +0900
Committer: Ingo Molnar <[email protected]>
CommitDate: Sun, 8 Nov 2009 10:19:17 +0100
perf bench: Add sched-messaging.c: Benchmark for scheduler and IPC mechanisms based on hackbench
This patch adds bench/sched-messaging.c.
This benchmark measures performance of scheduler and IPC
mechanisms, and is based on hackbench by Rusty Russell.
Example of usage:
% perf bench sched messaging -g 20 -l 1000 -s
5.432 # in sec
% perf bench sched messaging # run with default
options (20 sender and receiver processes per group)
(10 groups == 400 processes run)
Total time:0.308 sec
% perf bench sched messaging -t -g 20 # # be multi-thread,
with 20 groups (20 sender and receiver threads per group)
(20 groups == 800 threads run)
Total time:0.582 sec
( Rusty is the original author of hackbench.c and he said the code is
and was under the GPLv2 so fine to be merged. )
Signed-off-by: Hitoshi Mitake <[email protected]>
Acked-by: Rusty Russell <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: [email protected]
Cc: Jiri Kosina <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>
---
tools/perf/bench/sched-messaging.c | 332 ++++++++++++++++++++++++++++++++++++
1 files changed, 332 insertions(+), 0 deletions(-)
diff --git a/tools/perf/bench/sched-messaging.c b/tools/perf/bench/sched-messaging.c
new file mode 100644
index 0000000..36b62c5
--- /dev/null
+++ b/tools/perf/bench/sched-messaging.c
@@ -0,0 +1,332 @@
+/*
+ *
+ * builtin-bench-messaging.c
+ *
+ * messaging: Benchmark for scheduler and IPC mechanisms
+ *
+ * Based on hackbench by Rusty Russell <[email protected]>
+ * Ported to perf by Hitoshi Mitake <[email protected]>
+ *
+ */
+
+#include "../perf.h"
+#include "../util/util.h"
+#include "../util/parse-options.h"
+#include "../builtin.h"
+#include "bench.h"
+
+/* Test groups of 20 processes spraying to 20 receivers */
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <sys/poll.h>
+#include <limits.h>
+
+#define DATASIZE 100
+
+static int use_pipes = 0;
+static unsigned int loops = 100;
+static unsigned int thread_mode = 0;
+static unsigned int num_groups = 10;
+static int simple = 0;
+
+struct sender_context {
+ unsigned int num_fds;
+ int ready_out;
+ int wakefd;
+ int out_fds[0];
+};
+
+struct receiver_context {
+ unsigned int num_packets;
+ int in_fds[2];
+ int ready_out;
+ int wakefd;
+};
+
+static void barf(const char *msg)
+{
+ fprintf(stderr, "%s (error: %s)\n", msg, strerror(errno));
+ exit(1);
+}
+
+static void fdpair(int fds[2])
+{
+ if (use_pipes) {
+ if (pipe(fds) == 0)
+ return;
+ } else {
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == 0)
+ return;
+ }
+
+ barf(use_pipes ? "pipe()" : "socketpair()");
+}
+
+/* Block until we're ready to go */
+static void ready(int ready_out, int wakefd)
+{
+ char dummy;
+ struct pollfd pollfd = { .fd = wakefd, .events = POLLIN };
+
+ /* Tell them we're ready. */
+ if (write(ready_out, &dummy, 1) != 1)
+ barf("CLIENT: ready write");
+
+ /* Wait for "GO" signal */
+ if (poll(&pollfd, 1, -1) != 1)
+ barf("poll");
+}
+
+/* Sender sprays loops messages down each file descriptor */
+static void *sender(struct sender_context *ctx)
+{
+ char data[DATASIZE];
+ unsigned int i, j;
+
+ ready(ctx->ready_out, ctx->wakefd);
+
+ /* Now pump to every receiver. */
+ for (i = 0; i < loops; i++) {
+ for (j = 0; j < ctx->num_fds; j++) {
+ int ret, done = 0;
+
+again:
+ ret = write(ctx->out_fds[j], data + done,
+ sizeof(data)-done);
+ if (ret < 0)
+ barf("SENDER: write");
+ done += ret;
+ if (done < DATASIZE)
+ goto again;
+ }
+ }
+
+ return NULL;
+}
+
+
+/* One receiver per fd */
+static void *receiver(struct receiver_context* ctx)
+{
+ unsigned int i;
+
+ if (!thread_mode)
+ close(ctx->in_fds[1]);
+
+ /* Wait for start... */
+ ready(ctx->ready_out, ctx->wakefd);
+
+ /* Receive them all */
+ for (i = 0; i < ctx->num_packets; i++) {
+ char data[DATASIZE];
+ int ret, done = 0;
+
+again:
+ ret = read(ctx->in_fds[0], data + done, DATASIZE - done);
+ if (ret < 0)
+ barf("SERVER: read");
+ done += ret;
+ if (done < DATASIZE)
+ goto again;
+ }
+
+ return NULL;
+}
+
+static pthread_t create_worker(void *ctx, void *(*func)(void *))
+{
+ pthread_attr_t attr;
+ pthread_t childid;
+ int err;
+
+ if (!thread_mode) {
+ /* process mode */
+ /* Fork the receiver. */
+ switch (fork()) {
+ case -1:
+ barf("fork()");
+ break;
+ case 0:
+ (*func) (ctx);
+ exit(0);
+ break;
+ default:
+ break;
+ }
+
+ return (pthread_t)0;
+ }
+
+ if (pthread_attr_init(&attr) != 0)
+ barf("pthread_attr_init:");
+
+#ifndef __ia64__
+ if (pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN) != 0)
+ barf("pthread_attr_setstacksize");
+#endif
+
+ err = pthread_create(&childid, &attr, func, ctx);
+ if (err != 0) {
+ fprintf(stderr, "pthread_create failed: %s (%d)\n",
+ strerror(err), err);
+ exit(-1);
+ }
+ return childid;
+}
+
+static void reap_worker(pthread_t id)
+{
+ int proc_status;
+ void *thread_status;
+
+ if (!thread_mode) {
+ /* process mode */
+ wait(&proc_status);
+ if (!WIFEXITED(proc_status))
+ exit(1);
+ } else {
+ pthread_join(id, &thread_status);
+ }
+}
+
+/* One group of senders and receivers */
+static unsigned int group(pthread_t *pth,
+ unsigned int num_fds,
+ int ready_out,
+ int wakefd)
+{
+ unsigned int i;
+ struct sender_context *snd_ctx = malloc(sizeof(struct sender_context)
+ + num_fds * sizeof(int));
+
+ if (!snd_ctx)
+ barf("malloc()");
+
+ for (i = 0; i < num_fds; i++) {
+ int fds[2];
+ struct receiver_context *ctx = malloc(sizeof(*ctx));
+
+ if (!ctx)
+ barf("malloc()");
+
+
+ /* Create the pipe between client and server */
+ fdpair(fds);
+
+ ctx->num_packets = num_fds * loops;
+ ctx->in_fds[0] = fds[0];
+ ctx->in_fds[1] = fds[1];
+ ctx->ready_out = ready_out;
+ ctx->wakefd = wakefd;
+
+ pth[i] = create_worker(ctx, (void *)receiver);
+
+ snd_ctx->out_fds[i] = fds[1];
+ if (!thread_mode)
+ close(fds[0]);
+ }
+
+ /* Now we have all the fds, fork the senders */
+ for (i = 0; i < num_fds; i++) {
+ snd_ctx->ready_out = ready_out;
+ snd_ctx->wakefd = wakefd;
+ snd_ctx->num_fds = num_fds;
+
+ pth[num_fds+i] = create_worker(snd_ctx, (void *)sender);
+ }
+
+ /* Close the fds we have left */
+ if (!thread_mode)
+ for (i = 0; i < num_fds; i++)
+ close(snd_ctx->out_fds[i]);
+
+ /* Return number of children to reap */
+ return num_fds * 2;
+}
+
+static const struct option options[] = {
+ OPT_BOOLEAN('p', "pipe", &use_pipes,
+ "Use pipe() instead of socketpair()"),
+ OPT_BOOLEAN('t', "thread", &thread_mode,
+ "Be multi thread instead of multi process"),
+ OPT_INTEGER('g', "group", &num_groups,
+ "Specify number of groups"),
+ OPT_INTEGER('l', "loop", &loops,
+ "Specify number of loops"),
+ OPT_BOOLEAN('s', "simple-output", &simple,
+ "Do simple output (this maybe useful for"
+ "processing by scripts or graph tools like gnuplot)"),
+ OPT_END()
+};
+
+static const char * const bench_sched_message_usage[] = {
+ "perf bench sched messaging <options>",
+ NULL
+};
+
+int bench_sched_messaging(int argc, const char **argv,
+ const char *prefix __used)
+{
+ unsigned int i, total_children;
+ struct timeval start, stop, diff;
+ unsigned int num_fds = 20;
+ int readyfds[2], wakefds[2];
+ char dummy;
+ pthread_t *pth_tab;
+
+ argc = parse_options(argc, argv, options,
+ bench_sched_message_usage, 0);
+
+ pth_tab = malloc(num_fds * 2 * num_groups * sizeof(pthread_t));
+ if (!pth_tab)
+ barf("main:malloc()");
+
+ fdpair(readyfds);
+ fdpair(wakefds);
+
+ total_children = 0;
+ for (i = 0; i < num_groups; i++)
+ total_children += group(pth_tab+total_children, num_fds,
+ readyfds[1], wakefds[0]);
+
+ /* Wait for everyone to be ready */
+ for (i = 0; i < total_children; i++)
+ if (read(readyfds[0], &dummy, 1) != 1)
+ barf("Reading for readyfds");
+
+ gettimeofday(&start, NULL);
+
+ /* Kick them off */
+ if (write(wakefds[1], &dummy, 1) != 1)
+ barf("Writing to start them");
+
+ /* Reap them all */
+ for (i = 0; i < total_children; i++)
+ reap_worker(pth_tab[i]);
+
+ gettimeofday(&stop, NULL);
+
+ timersub(&stop, &start, &diff);
+
+ if (simple)
+ printf("%lu.%03lu\n", diff.tv_sec, diff.tv_usec/1000);
+ else {
+ printf("(%d sender and receiver %s per group)\n",
+ num_fds, thread_mode ? "threads" : "processes");
+ printf("(%d groups == %d %s run)\n\n",
+ num_groups, num_groups * 2 * num_fds,
+ thread_mode ? "threads" : "processes");
+ printf("\tTotal time:%lu.%03lu sec\n",
+ diff.tv_sec, diff.tv_usec/1000);
+ }
+
+ return 0;
+}
Commit-ID: c7d9300f367f480aee4663a0e3695c5b48859a1a
Gitweb: http://git.kernel.org/tip/c7d9300f367f480aee4663a0e3695c5b48859a1a
Author: Hitoshi Mitake <[email protected]>
AuthorDate: Thu, 5 Nov 2009 09:31:33 +0900
Committer: Ingo Molnar <[email protected]>
CommitDate: Sun, 8 Nov 2009 10:19:18 +0100
perf bench: Add sched-pipe.c: Benchmark for pipe() system call
This patch adds bench/sched-pipe.c.
bench/sched-pipe.c is a benchmark program
to measure performance of pipe() system call.
This benchmark is based on pipe-test-1m.c by Ingo Molnar:
http://people.redhat.com/mingo/cfs-scheduler/tools/pipe-test-1m.c
Example of use:
% perf bench sched pipe
(executing 1000000 pipe operations between two tasks)
Total time:4.499 sec
4.499179 usecs/op
222262 ops/sec
% perf bench sched pipe -s -l 1000
0.015
Signed-off-by: Hitoshi Mitake <[email protected]>
Cc: Rusty Russell <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: [email protected]
Cc: Jiri Kosina <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>
---
tools/perf/bench/sched-pipe.c | 113 +++++++++++++++++++++++++++++++++++++++++
1 files changed, 113 insertions(+), 0 deletions(-)
diff --git a/tools/perf/bench/sched-pipe.c b/tools/perf/bench/sched-pipe.c
new file mode 100644
index 0000000..3214ed2
--- /dev/null
+++ b/tools/perf/bench/sched-pipe.c
@@ -0,0 +1,113 @@
+/*
+ *
+ * builtin-bench-pipe.c
+ *
+ * pipe: Benchmark for pipe()
+ *
+ * Based on pipe-test-1m.c by Ingo Molnar <[email protected]>
+ * http://people.redhat.com/mingo/cfs-scheduler/tools/pipe-test-1m.c
+ * Ported to perf by Hitoshi Mitake <[email protected]>
+ *
+ */
+
+#include "../perf.h"
+#include "../util/util.h"
+#include "../util/parse-options.h"
+#include "../builtin.h"
+#include "bench.h"
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <linux/unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <sys/time.h>
+
+#define LOOPS_DEFAULT 1000000
+static int loops = LOOPS_DEFAULT;
+static int simple = 0;
+
+static const struct option options[] = {
+ OPT_INTEGER('l', "loop", &loops,
+ "Specify number of loops"),
+ OPT_BOOLEAN('s', "simple-output", &simple,
+ "Do simple output (this maybe useful for"
+ "processing by scripts or graph tools like gnuplot)"),
+ OPT_END()
+};
+
+static const char * const bench_sched_pipe_usage[] = {
+ "perf bench sched pipe <options>",
+ NULL
+};
+
+int bench_sched_pipe(int argc, const char **argv,
+ const char *prefix __used)
+{
+ int pipe_1[2], pipe_2[2];
+ int m = 0, i;
+ struct timeval start, stop, diff;
+ unsigned long long result_usec = 0;
+
+ /*
+ * why does "ret" exist?
+ * discarding returned value of read(), write()
+ * causes error in building environment for perf
+ */
+ int ret;
+ pid_t pid;
+
+ argc = parse_options(argc, argv, options,
+ bench_sched_pipe_usage, 0);
+
+ assert(!pipe(pipe_1));
+ assert(!pipe(pipe_2));
+
+ pid = fork();
+ assert(pid >= 0);
+
+ gettimeofday(&start, NULL);
+
+ if (!pid) {
+ for (i = 0; i < loops; i++) {
+ ret = read(pipe_1[0], &m, sizeof(int));
+ ret = write(pipe_2[1], &m, sizeof(int));
+ }
+ } else {
+ for (i = 0; i < loops; i++) {
+ ret = write(pipe_1[1], &m, sizeof(int));
+ ret = read(pipe_2[0], &m, sizeof(int));
+ }
+ }
+
+ gettimeofday(&stop, NULL);
+ timersub(&stop, &start, &diff);
+
+ if (pid)
+ return 0;
+
+ if (simple)
+ printf("%lu.%03lu\n",
+ diff.tv_sec, diff.tv_usec / 1000);
+ else {
+ printf("(executing %d pipe operations between two tasks)\n\n",
+ loops);
+
+ result_usec = diff.tv_sec * 1000000;
+ result_usec += diff.tv_usec;
+
+ printf("\tTotal time:%lu.%03lu sec\n",
+ diff.tv_sec, diff.tv_usec / 1000);
+ printf("\t\t%lf usecs/op\n",
+ (double)result_usec / (double)loops);
+ printf("\t\t%d ops/sec\n",
+ (int)((double)loops /
+ ((double)result_usec / (double)1000000)));
+ }
+
+ return 0;
+}
Commit-ID: 629cc356653719c206a05f4dee5c5e242edb6546
Gitweb: http://git.kernel.org/tip/629cc356653719c206a05f4dee5c5e242edb6546
Author: Hitoshi Mitake <[email protected]>
AuthorDate: Thu, 5 Nov 2009 09:31:34 +0900
Committer: Ingo Molnar <[email protected]>
CommitDate: Sun, 8 Nov 2009 10:19:18 +0100
perf bench: Add builtin-bench.c: General framework for benchmark suites
This patch adds builtin-bench.c
builtin-bench.c is a general framework for benchmark suites.
Signed-off-by: Hitoshi Mitake <[email protected]>
Cc: Rusty Russell <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: [email protected]
Cc: Jiri Kosina <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>
---
tools/perf/builtin-bench.c | 128 ++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 128 insertions(+), 0 deletions(-)
diff --git a/tools/perf/builtin-bench.c b/tools/perf/builtin-bench.c
new file mode 100644
index 0000000..31f4164
--- /dev/null
+++ b/tools/perf/builtin-bench.c
@@ -0,0 +1,128 @@
+/*
+ *
+ * builtin-bench.c
+ *
+ * General benchmarking subsystem provided by perf
+ *
+ * Copyright (C) 2009, Hitoshi Mitake <[email protected]>
+ *
+ */
+
+/*
+ *
+ * Available subsystem list:
+ * sched ... scheduler and IPC mechanism
+ *
+ */
+
+#include "perf.h"
+#include "util/util.h"
+#include "util/parse-options.h"
+#include "builtin.h"
+#include "bench/bench.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct bench_suite {
+ const char *name;
+ const char *summary;
+ int (*fn)(int, const char **, const char *);
+};
+
+static struct bench_suite sched_suites[] = {
+ { "messaging",
+ "Benchmark for scheduler and IPC mechanisms",
+ bench_sched_messaging },
+ { "pipe",
+ "Flood of communication over pipe() between two processes",
+ bench_sched_pipe },
+ { NULL,
+ NULL,
+ NULL }
+};
+
+struct bench_subsys {
+ const char *name;
+ const char *summary;
+ struct bench_suite *suites;
+};
+
+static struct bench_subsys subsystems[] = {
+ { "sched",
+ "scheduler and IPC mechanism",
+ sched_suites },
+ { NULL,
+ NULL,
+ NULL }
+};
+
+static void dump_suites(int subsys_index)
+{
+ int i;
+
+ printf("List of available suites for %s...\n\n",
+ subsystems[subsys_index].name);
+
+ for (i = 0; subsystems[subsys_index].suites[i].name; i++)
+ printf("\t%s: %s\n",
+ subsystems[subsys_index].suites[i].name,
+ subsystems[subsys_index].suites[i].summary);
+
+ printf("\n");
+ return;
+}
+
+int cmd_bench(int argc, const char **argv, const char *prefix __used)
+{
+ int i, j, status = 0;
+
+ if (argc < 2) {
+ /* No subsystem specified. */
+ printf("Usage: perf bench <subsystem> <suite> [<options>]\n\n");
+ printf("List of available subsystems...\n\n");
+
+ for (i = 0; subsystems[i].name; i++)
+ printf("\t%s: %s\n",
+ subsystems[i].name, subsystems[i].summary);
+ printf("\n");
+
+ goto end;
+ }
+
+ for (i = 0; subsystems[i].name; i++) {
+ if (strcmp(subsystems[i].name, argv[1]))
+ continue;
+
+ if (argc < 3) {
+ /* No suite specified. */
+ dump_suites(i);
+ goto end;
+ }
+
+ for (j = 0; subsystems[i].suites[j].name; j++) {
+ if (strcmp(subsystems[i].suites[j].name, argv[2]))
+ continue;
+
+ status = subsystems[i].suites[j].fn(argc - 2,
+ argv + 2, prefix);
+ goto end;
+ }
+
+ if (!strcmp(argv[2], "-h") || !strcmp(argv[2], "--help")) {
+ dump_suites(i);
+ goto end;
+ }
+
+ printf("Unknown suite:%s for %s\n", argv[2], argv[1]);
+ status = 1;
+ goto end;
+ }
+
+ printf("Unknown subsystem:%s\n", argv[1]);
+ status = 1;
+
+end:
+ return status;
+}
Commit-ID: 11bd341c043348ecb7462d3bd8e1ad6d00f6892a
Gitweb: http://git.kernel.org/tip/11bd341c043348ecb7462d3bd8e1ad6d00f6892a
Author: Hitoshi Mitake <[email protected]>
AuthorDate: Thu, 5 Nov 2009 09:31:35 +0900
Committer: Ingo Molnar <[email protected]>
CommitDate: Sun, 8 Nov 2009 10:19:19 +0100
perf bench: Modify builtin.h for new prototype
This patch modifies builtin.h to add prototype of cmd_bench().
Signed-off-by: Hitoshi Mitake <[email protected]>
Cc: Rusty Russell <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: [email protected]
Cc: Jiri Kosina <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>
---
tools/perf/builtin.h | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h
index e11d8d2..f0cd5b1 100644
--- a/tools/perf/builtin.h
+++ b/tools/perf/builtin.h
@@ -15,6 +15,7 @@ extern int read_line_with_nul(char *buf, int size, FILE *file);
extern int check_pager_config(const char *cmd);
extern int cmd_annotate(int argc, const char **argv, const char *prefix);
+extern int cmd_bench(int argc, const char **argv, const char *prefix);
extern int cmd_help(int argc, const char **argv, const char *prefix);
extern int cmd_sched(int argc, const char **argv, const char *prefix);
extern int cmd_list(int argc, const char **argv, const char *prefix);
Commit-ID: dcba8848d3bc83ec9ee0858b9ae6e4f1c1fa7fa3
Gitweb: http://git.kernel.org/tip/dcba8848d3bc83ec9ee0858b9ae6e4f1c1fa7fa3
Author: Hitoshi Mitake <[email protected]>
AuthorDate: Thu, 5 Nov 2009 09:31:36 +0900
Committer: Ingo Molnar <[email protected]>
CommitDate: Sun, 8 Nov 2009 10:19:19 +0100
perf bench: Add new subcommand 'bench' to perf.c
This patch modifies perf.c for invoking 'bench' subcommand.
Signed-off-by: Hitoshi Mitake <[email protected]>
Cc: Rusty Russell <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: [email protected]
Cc: Jiri Kosina <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>
---
tools/perf/perf.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 624e62d..f90ca5e 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -288,6 +288,7 @@ static void handle_internal_command(int argc, const char **argv)
{ "list", cmd_list, 0 },
{ "record", cmd_record, 0 },
{ "report", cmd_report, 0 },
+ { "bench", cmd_bench, 0 },
{ "stat", cmd_stat, 0 },
{ "timechart", cmd_timechart, 0 },
{ "top", cmd_top, 0 },
Commit-ID: bfde82ef51e3ea6ab8634d0fdbf5adcdd1b429cb
Gitweb: http://git.kernel.org/tip/bfde82ef51e3ea6ab8634d0fdbf5adcdd1b429cb
Author: Hitoshi Mitake <[email protected]>
AuthorDate: Thu, 5 Nov 2009 09:31:37 +0900
Committer: Ingo Molnar <[email protected]>
CommitDate: Sun, 8 Nov 2009 10:19:20 +0100
perf bench: Add subcommand 'bench' to the Makefile
This patch modifies Makefile for new files related to 'bench'
subcommand. The new code is active from this point on.
Signed-off-by: Hitoshi Mitake <[email protected]>
Cc: Rusty Russell <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: [email protected]
Cc: Jiri Kosina <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>
---
tools/perf/Makefile | 7 +++++++
1 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 542b29e..0a25428 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -416,6 +416,13 @@ LIB_OBJS += util/hist.o
LIB_OBJS += util/data_map.o
BUILTIN_OBJS += builtin-annotate.o
+
+BUILTIN_OBJS += builtin-bench.o
+
+# Benchmark modules
+BUILTIN_OBJS += bench/sched-messaging.o
+BUILTIN_OBJS += bench/sched-pipe.o
+
BUILTIN_OBJS += builtin-help.o
BUILTIN_OBJS += builtin-sched.o
BUILTIN_OBJS += builtin-list.o
From: Ingo Molnar <[email protected]>
Subject: Re: [PATCH v5 0/7] Adding general performance benchmarking subcommand to perf.
Date: Sun, 8 Nov 2009 10:21:21 +0100
>
> * Hitoshi Mitake <[email protected]> wrote:
>
> > This patch series add general benchmark subcommand to perf.
> >
> > The subcommand will unify the benchmarking programs
> > and provide these in standardized way.
> >
> > I fixed this series for latest tip tree.
> > My previous patch series conflicts with cmd_probe().
> > So please discard v4 and use this v5.
> >
> > Hitoshi Mitake (7):
> > Adding new directory and header for new subcommand 'bench'
> > sched-messaging.c: benchmark for scheduler and IPC mechanisms based
> > on hackbench
> > sched-pipe.c: benchmark for pipe() system call
> > builtin-bench.c: General framework for benchmark suites
> > Modifying builtin.h for new prototype
> > Modyfing perf.c for subcommand 'bench'
> > Modyfing Makefile to build subcommand 'bench'
> >
> > tools/perf/Makefile | 6 +
> > tools/perf/bench/bench.h | 9 +
> > tools/perf/bench/sched-messaging.c | 332 ++++++++++++++++++++++++++++++++++++
> > tools/perf/bench/sched-pipe.c | 113 ++++++++++++
> > tools/perf/builtin-bench.c | 128 ++++++++++++++
> > tools/perf/builtin.h | 1 +
> > tools/perf/perf.c | 1 +
> > 7 files changed, 590 insertions(+), 0 deletions(-)
> > create mode 100644 tools/perf/bench/bench.h
> > create mode 100644 tools/perf/bench/sched-messaging.c
> > create mode 100644 tools/perf/bench/sched-pipe.c
> > create mode 100644 tools/perf/builtin-bench.c
>
> Looks good - i've applied the patches to tip:perf/bench, thanks!
Thanks! Then I'll work on documentation and merging other
benchmarks such like lmbench or copybench.
>
> There's one small bug i noticed:
>
> $ ./perf bench sched pipe
> (executing 1000000 pipe operations between two tasks)
>
> Total time:4.898 sec
> $ 4.898586 usecs/op
> 204140 ops/sec
>
>
> the shell prompt came back before the usecs/op and ops/sec line was
> printed. Process teardown race, lack of wait() or so?
Thanks for your notify. I prepared a patch to fix this problem.
I'll send it later.
Fixed bench/sched-pipe.c to avoid the below case
notified by Ingo Molnar,
---
$ ./perf bench sched pipe
(executing 1000000 pipe operations between two tasks)
Total time:4.898 sec
$ 4.898586 usecs/op
204140 ops/sec
the shell prompt came back before the usecs/op and ops/sec line was
printed. Process teardown race, lack of wait() or so?
---
This caused by lack of calling waitpid() by parent process,
so I added it.
Signed-off-by: Hitoshi Mitake <[email protected]>
Cc: Rusty Russell <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Kosina <[email protected]>
---
tools/perf/bench/sched-pipe.c | 10 +++++++---
1 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/tools/perf/bench/sched-pipe.c b/tools/perf/bench/sched-pipe.c
index 3214ed2..6a29100 100644
--- a/tools/perf/bench/sched-pipe.c
+++ b/tools/perf/bench/sched-pipe.c
@@ -26,6 +26,7 @@
#include <errno.h>
#include <assert.h>
#include <sys/time.h>
+#include <sys/types.h>
#define LOOPS_DEFAULT 1000000
static int loops = LOOPS_DEFAULT;
@@ -58,8 +59,8 @@ int bench_sched_pipe(int argc, const char **argv,
* discarding returned value of read(), write()
* causes error in building environment for perf
*/
- int ret;
- pid_t pid;
+ int ret, wait_stat;
+ pid_t pid, retpid;
argc = parse_options(argc, argv, options,
bench_sched_pipe_usage, 0);
@@ -87,8 +88,11 @@ int bench_sched_pipe(int argc, const char **argv,
gettimeofday(&stop, NULL);
timersub(&stop, &start, &diff);
- if (pid)
+ if (pid) {
+ retpid = waitpid(pid, &wait_stat, 0);
+ assert((retpid == pid) && WIFEXITED(wait_stat));
return 0;
+ }
if (simple)
printf("%lu.%03lu\n",
--
1.6.5.2
From: Hitoshi Mitake <[email protected]>
Subject: [PATCH] perf bench:Fix bench/sched-pipe.c to wait child process
Date: Mon, 9 Nov 2009 12:13:08 +0900
Sorry, the title lacks space after "perf bench:".
I'll send new fixed one, please discard this.
> Fixed bench/sched-pipe.c to avoid the below case
> notified by Ingo Molnar,
>
> ---
>
> $ ./perf bench sched pipe
> (executing 1000000 pipe operations between two tasks)
>
> Total time:4.898 sec
> $ 4.898586 usecs/op
> 204140 ops/sec
>
> the shell prompt came back before the usecs/op and ops/sec line was
> printed. Process teardown race, lack of wait() or so?
>
> ---
>
> This caused by lack of calling waitpid() by parent process,
> so I added it.
>
> Signed-off-by: Hitoshi Mitake <[email protected]>
> Cc: Rusty Russell <[email protected]>
> Cc: Peter Zijlstra <[email protected]>
> Cc: Paul Mackerras <[email protected]>
> Cc: Mike Galbraith <[email protected]>
> Cc: Arnaldo Carvalho de Melo <[email protected]>
> Cc: Frederic Weisbecker <[email protected]>
> Cc: Jiri Kosina <[email protected]>
> ---
> tools/perf/bench/sched-pipe.c | 10 +++++++---
> 1 files changed, 7 insertions(+), 3 deletions(-)
>
> diff --git a/tools/perf/bench/sched-pipe.c b/tools/perf/bench/sched-pipe.c
> index 3214ed2..6a29100 100644
> --- a/tools/perf/bench/sched-pipe.c
> +++ b/tools/perf/bench/sched-pipe.c
> @@ -26,6 +26,7 @@
> #include <errno.h>
> #include <assert.h>
> #include <sys/time.h>
> +#include <sys/types.h>
>
> #define LOOPS_DEFAULT 1000000
> static int loops = LOOPS_DEFAULT;
> @@ -58,8 +59,8 @@ int bench_sched_pipe(int argc, const char **argv,
> * discarding returned value of read(), write()
> * causes error in building environment for perf
> */
> - int ret;
> - pid_t pid;
> + int ret, wait_stat;
> + pid_t pid, retpid;
>
> argc = parse_options(argc, argv, options,
> bench_sched_pipe_usage, 0);
> @@ -87,8 +88,11 @@ int bench_sched_pipe(int argc, const char **argv,
> gettimeofday(&stop, NULL);
> timersub(&stop, &start, &diff);
>
> - if (pid)
> + if (pid) {
> + retpid = waitpid(pid, &wait_stat, 0);
> + assert((retpid == pid) && WIFEXITED(wait_stat));
> return 0;
> + }
>
> if (simple)
> printf("%lu.%03lu\n",
> --
> 1.6.5.2
>
>
Fixed bench/sched-pipe.c to avoid the below case
notified by Ingo Molnar,
---
$ ./perf bench sched pipe
(executing 1000000 pipe operations between two tasks)
Total time:4.898 sec
$ 4.898586 usecs/op
204140 ops/sec
the shell prompt came back before the usecs/op and ops/sec line was
printed. Process teardown race, lack of wait() or so?
---
This caused by lack of calling waitpid() by parent process,
so I added it.
Signed-off-by: Hitoshi Mitake <[email protected]>
Cc: Rusty Russell <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Kosina <[email protected]>
---
tools/perf/bench/sched-pipe.c | 10 +++++++---
1 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/tools/perf/bench/sched-pipe.c b/tools/perf/bench/sched-pipe.c
index 3214ed2..6a29100 100644
--- a/tools/perf/bench/sched-pipe.c
+++ b/tools/perf/bench/sched-pipe.c
@@ -26,6 +26,7 @@
#include <errno.h>
#include <assert.h>
#include <sys/time.h>
+#include <sys/types.h>
#define LOOPS_DEFAULT 1000000
static int loops = LOOPS_DEFAULT;
@@ -58,8 +59,8 @@ int bench_sched_pipe(int argc, const char **argv,
* discarding returned value of read(), write()
* causes error in building environment for perf
*/
- int ret;
- pid_t pid;
+ int ret, wait_stat;
+ pid_t pid, retpid;
argc = parse_options(argc, argv, options,
bench_sched_pipe_usage, 0);
@@ -87,8 +88,11 @@ int bench_sched_pipe(int argc, const char **argv,
gettimeofday(&stop, NULL);
timersub(&stop, &start, &diff);
- if (pid)
+ if (pid) {
+ retpid = waitpid(pid, &wait_stat, 0);
+ assert((retpid == pid) && WIFEXITED(wait_stat));
return 0;
+ }
if (simple)
printf("%lu.%03lu\n",
--
1.6.5.2
Commit-ID: 5ff0cfc67f00fe0feaa1da0b2359232ea4aa0ee7
Gitweb: http://git.kernel.org/tip/5ff0cfc67f00fe0feaa1da0b2359232ea4aa0ee7
Author: Hitoshi Mitake <[email protected]>
AuthorDate: Mon, 9 Nov 2009 12:31:05 +0900
Committer: Ingo Molnar <[email protected]>
CommitDate: Mon, 9 Nov 2009 08:14:30 +0100
perf bench: Fix bench/sched-pipe.c to wait for child process
Ingo reported this small 'perf bench sched pipe' output problem:
| $ ./perf bench sched pipe
| (executing 1000000 pipe operations between two tasks)
|
| Total time:4.898 sec
| $ 4.898586 usecs/op
| 204140 ops/sec
|
| the shell prompt came back before the usecs/op and ops/sec line
| was printed. Process teardown race, lack of wait() or so?
This caused by lack of calling waitpid() by parent process,
so I added it.
Signed-off-by: Hitoshi Mitake <[email protected]>
Cc: Rusty Russell <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Kosina <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>
---
tools/perf/bench/sched-pipe.c | 10 +++++++---
1 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/tools/perf/bench/sched-pipe.c b/tools/perf/bench/sched-pipe.c
index 3214ed2..6a29100 100644
--- a/tools/perf/bench/sched-pipe.c
+++ b/tools/perf/bench/sched-pipe.c
@@ -26,6 +26,7 @@
#include <errno.h>
#include <assert.h>
#include <sys/time.h>
+#include <sys/types.h>
#define LOOPS_DEFAULT 1000000
static int loops = LOOPS_DEFAULT;
@@ -58,8 +59,8 @@ int bench_sched_pipe(int argc, const char **argv,
* discarding returned value of read(), write()
* causes error in building environment for perf
*/
- int ret;
- pid_t pid;
+ int ret, wait_stat;
+ pid_t pid, retpid;
argc = parse_options(argc, argv, options,
bench_sched_pipe_usage, 0);
@@ -87,8 +88,11 @@ int bench_sched_pipe(int argc, const char **argv,
gettimeofday(&stop, NULL);
timersub(&stop, &start, &diff);
- if (pid)
+ if (pid) {
+ retpid = waitpid(pid, &wait_stat, 0);
+ assert((retpid == pid) && WIFEXITED(wait_stat));
return 0;
+ }
if (simple)
printf("%lu.%03lu\n",