benchmarks: add hackbench benchmark for scheduler performance

Signed-off-by: Chen Hui <cedriccchen@tencent.com>
This commit is contained in:
Chen Hui
2022-09-23 12:32:16 +08:00
parent b448cdbed7
commit b63b4d6f36
5 changed files with 175 additions and 0 deletions
+6
View File
@@ -0,0 +1,6 @@
FROM ubuntu:18.04
RUN set -x \
&& apt-get update \
&& apt-get install -y rt-tests \
&& rm -rf /var/lib/apt/lists/*
+11
View File
@@ -59,3 +59,14 @@ benchmark_test(
"//test/benchmarks/tools",
],
)
benchmark_test(
name = "hackbench_test",
srcs = ["hackbench_test.go"],
visibility = ["//:sandbox"],
deps = [
"//pkg/test/dockerutil",
"//test/benchmarks/harness",
"//test/benchmarks/tools",
],
)
+89
View File
@@ -0,0 +1,89 @@
// Copyright 2022 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package hackbench_test
import (
"context"
"os"
"testing"
"gvisor.dev/gvisor/pkg/test/dockerutil"
"gvisor.dev/gvisor/test/benchmarks/harness"
"gvisor.dev/gvisor/test/benchmarks/tools"
)
// BenchmarHackbench runs hackbench on the runtime.
func BenchmarkHackbench(b *testing.B) {
testCases := []tools.Hackbench{
{
IpcMode: "pipe",
ProcessMode: "thread",
},
{
IpcMode: "socket",
ProcessMode: "process",
},
}
machine, err := harness.GetMachine()
if err != nil {
b.Fatalf("failed to get machine: %v", err)
}
defer machine.CleanUp()
for _, tc := range testCases {
ipcMode := tools.Parameter{
Name: "ipcMode",
Value: tc.IpcMode,
}
processMode := tools.Parameter{
Name: "processMode",
Value: tc.ProcessMode,
}
name, err := tools.ParametersToName(ipcMode, processMode)
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/hackbench",
},
"sleep", "24h",
); err != nil {
b.Fatalf("run failed with: %v", err)
}
cmd := tc.MakeCmd(b)
b.ResetTimer()
out, err := container.Exec(ctx, dockerutil.ExecOpts{}, cmd...)
if err != nil {
b.Fatalf("failed to run hackbench: %v, logs:%s", err, out)
}
tc.Report(b, out)
})
}
}
// TestMain is the main method for this package.
func TestMain(m *testing.M) {
harness.Init()
harness.SetFixedBenchmarks()
os.Exit(m.Run())
}
+1
View File
@@ -14,6 +14,7 @@ go_library(
"parser_util.go",
"redis.go",
"sysbench.go",
"hackbench.go",
"tools.go",
],
visibility = ["//:sandbox"],
+68
View File
@@ -0,0 +1,68 @@
// Copyright 2022 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package tools
import (
"fmt"
"regexp"
"strconv"
"testing"
)
// Hackbench makes 'hackbench' commands and parses their output.
type Hackbench struct {
IpcMode string // ipc mode: pipe, socket(default)
ProcessMode string // process mode: thread, process(default)
}
// MakeCmd makes commands for Hackbench.
func (s *Hackbench) MakeCmd(b *testing.B) []string {
cmd := []string{"hackbench"}
// ipc mode
if s.IpcMode == "pipe" {
cmd = append(cmd, "--pipe")
}
// group num
cmd = append(cmd, "--groups=10")
// process mode
if s.ProcessMode == "thread" {
cmd = append(cmd, "--threads")
} else {
cmd = append(cmd, "--process")
}
// loops
cmd = append(cmd, "--loops=1000")
return cmd
}
// Report reports the relevant metrics for Hackbench.
func (s *Hackbench) Report(b *testing.B, output string) {
b.Helper()
result, err := s.parseResult(output)
if err != nil {
b.Fatalf("parsing result from %s failed: %v", output, err)
}
ReportCustomMetric(b, result, "execution_time" /*metric name*/, "s" /*unit*/)
}
var hackbenchRegexp = regexp.MustCompile(`Time:\s*(\d*.?\d*)\n`)
func (s *Hackbench) parseResult(data string) (float64, error) {
match := hackbenchRegexp.FindStringSubmatch(data)
if len(match) < 2 {
return 0.0, fmt.Errorf("could not find Time: %s", data)
}
return strconv.ParseFloat(match[1], 64)
}