From 5a6447f491af0530e9e3a1985ed996817410b818 Mon Sep 17 00:00:00 2001 From: Zach Koopmans Date: Thu, 2 Mar 2023 15:35:41 -0800 Subject: [PATCH] Add getpidopt case to docker benchmarks. getpidopt is an important test case for the systrap platform, so add it to our syscall test. PiperOrigin-RevId: 513657968 --- .../{Dockerfile => Dockerfile.x86_64} | 0 images/benchmarks/syscallbench/syscallbench.c | 51 +++++++++++-- test/benchmarks/base/syscallbench_test.go | 71 ++++++++++++------- 3 files changed, 88 insertions(+), 34 deletions(-) rename images/benchmarks/syscallbench/{Dockerfile => Dockerfile.x86_64} (100%) diff --git a/images/benchmarks/syscallbench/Dockerfile b/images/benchmarks/syscallbench/Dockerfile.x86_64 similarity index 100% rename from images/benchmarks/syscallbench/Dockerfile rename to images/benchmarks/syscallbench/Dockerfile.x86_64 diff --git a/images/benchmarks/syscallbench/syscallbench.c b/images/benchmarks/syscallbench/syscallbench.c index de88e0e1d..11912916a 100644 --- a/images/benchmarks/syscallbench/syscallbench.c +++ b/images/benchmarks/syscallbench/syscallbench.c @@ -20,21 +20,39 @@ static int loops = 10000000; +enum syscall_type { get_pid, get_pid_opt }; + +#ifdef __x86_64__ + +#define SYSNO_STR1(x) #x +#define SYSNO_STR(x) SYSNO_STR1(x) + +void do_getpidopt() { + __asm__("movl $" SYSNO_STR(SYS_getpid) ", %%eax\n" + "syscall\n" + : : : "rax", "rcx", "r11"); +} +#endif + static void show_usage(const char *cmd) { fprintf(stderr, "Usage: %s [options]\n" - "-l, --loops \t\t Number of syscall loops, default 10000000\n", - cmd); + "-l, --loops \t\t Number of syscall loops, default 10000000\n" + "-s, --syscall \t\tSyscall to run (default getpid)\n" + "\tOptions:\n" + "\t%d) getpid\n" + "\t%d) getpidopt\n", + cmd, get_pid, get_pid_opt); } int main(int argc, char *argv[]) { - int i; - int c; + int i, c, sys_val = get_pid; struct option long_options[] = {{"loops", required_argument, 0, 'l'}, + {"syscall", required_argument, 0, 's'}, {0, 0, 0, 0}}; int option_index = 0; - while ((c = getopt_long(argc, argv, "l:", long_options, &option_index)) != + while ((c = getopt_long(argc, argv, "l:s", long_options, &option_index)) != -1) { switch (c) { case 'l': @@ -44,14 +62,33 @@ int main(int argc, char *argv[]) { exit(1); } break; + case 's': + sys_val = atoi(optarg); + if (sys_val < 0) { + show_usage(argv[0]); + exit(1); + } + break; default: + fprintf(stderr, "unknown option: '%c'\n", c); show_usage(argv[0]); exit(1); } } - for (i = 0; i < loops; i++) syscall(SYS_getpid); + switch (sys_val) { + case (int)get_pid: + for (i = 0; i < loops; i++) syscall(SYS_getpid); + break; + case (int)get_pid_opt: + for (i = 0; i < loops; i++) do_getpidopt(); + break; + default: + fprintf(stderr, "unknown syscall option: %d\n", sys_val); + show_usage(argv[0]); + exit(1); + } - printf("# Executed %'d getpid() calls\n", loops); + printf("# Executed %'d calls\n", loops); return 0; } diff --git a/test/benchmarks/base/syscallbench_test.go b/test/benchmarks/base/syscallbench_test.go index 092b76ef4..3e9881a76 100644 --- a/test/benchmarks/base/syscallbench_test.go +++ b/test/benchmarks/base/syscallbench_test.go @@ -24,41 +24,58 @@ import ( "gvisor.dev/gvisor/test/benchmarks/tools" ) -// BenchmarSyscallbench runs syscallbench on the runtime. +// BenchmarSyscallbench runs a syscall b.N times on the runtime. func BenchmarkSyscallbench(b *testing.B) { + ctx := context.Background() machine, err := harness.GetMachine() if err != nil { b.Fatalf("failed to get machine: %v", err) } defer machine.CleanUp() - param := tools.Parameter{ - Name: "syscall", - Value: "getpid", - } - name, err := tools.ParametersToName(param) - if err != nil { - b.Fatalf("Failed to parse params: %v", err) - } - b.Run(name, func(b *testing.B) { - ctx := context.Background() - container := machine.GetContainer(ctx, b) - defer container.CleanUp(ctx) - - if err := container.Spawn( - ctx, dockerutil.RunOpts{ - Image: "benchmarks/syscallbench", + for _, tc := range []struct { + param tools.Parameter + syscallArg int + }{ + { + param: tools.Parameter{ + Name: "syscall", + Value: "getpid", }, - "sleep", "24h", - ); err != nil { - b.Fatalf("run failed with: %v", err) + }, + { + param: tools.Parameter{ + Name: "syscall", + Value: "getpidopt", + }, + syscallArg: 1, + }, + } { + name, err := tools.ParametersToName(tc.param) + if err != nil { + b.Fatalf("Failed to parse params: %v", err) } - cmd := []string{"syscallbench", fmt.Sprintf("--loops=%d", b.N)} - b.ResetTimer() - out, err := container.Exec(ctx, dockerutil.ExecOpts{}, cmd...) - if err != nil { - b.Fatalf("failed to run syscallbench: %v, logs:%s", err, out) - } - }) + func() { + container := machine.GetContainer(ctx, b) + defer container.CleanUp(ctx) + if err := container.Spawn( + ctx, dockerutil.RunOpts{ + Image: "benchmarks/syscallbench", + }, + "sleep", "24h", + ); err != nil { + b.Fatalf("run failed with: %v", err) + } + b.Run(name, func(b *testing.B) { + cmd := []string{"syscallbench", fmt.Sprintf("--loops=%d --syscall %d", b.N, tc.syscallArg)} + b.ResetTimer() + out, err := container.Exec(ctx, dockerutil.ExecOpts{}, cmd...) + if err != nil { + b.Fatalf("failed to run syscallbench: %v, logs:%s", err, out) + } + }) + }() + } + }