diff options
Diffstat (limited to 'test/benchmarks/tools')
-rw-r--r-- | test/benchmarks/tools/BUILD | 35 | ||||
-rw-r--r-- | test/benchmarks/tools/ab.go | 97 | ||||
-rw-r--r-- | test/benchmarks/tools/ab_test.go | 90 | ||||
-rw-r--r-- | test/benchmarks/tools/fio.go | 124 | ||||
-rw-r--r-- | test/benchmarks/tools/fio_test.go | 122 | ||||
-rw-r--r-- | test/benchmarks/tools/hey.go | 75 | ||||
-rw-r--r-- | test/benchmarks/tools/hey_test.go | 81 | ||||
-rw-r--r-- | test/benchmarks/tools/iperf.go | 56 | ||||
-rw-r--r-- | test/benchmarks/tools/iperf_test.go | 34 | ||||
-rw-r--r-- | test/benchmarks/tools/meminfo.go | 60 | ||||
-rw-r--r-- | test/benchmarks/tools/meminfo_test.go | 84 | ||||
-rw-r--r-- | test/benchmarks/tools/parser_util.go | 101 | ||||
-rw-r--r-- | test/benchmarks/tools/redis.go | 63 | ||||
-rw-r--r-- | test/benchmarks/tools/redis_test.go | 87 | ||||
-rw-r--r-- | test/benchmarks/tools/sysbench.go | 245 | ||||
-rw-r--r-- | test/benchmarks/tools/sysbench_test.go | 169 | ||||
-rw-r--r-- | test/benchmarks/tools/tools.go | 17 |
17 files changed, 0 insertions, 1540 deletions
diff --git a/test/benchmarks/tools/BUILD b/test/benchmarks/tools/BUILD deleted file mode 100644 index 9290830d7..000000000 --- a/test/benchmarks/tools/BUILD +++ /dev/null @@ -1,35 +0,0 @@ -load("//tools:defs.bzl", "go_library", "go_test") - -package(licenses = ["notice"]) - -go_library( - name = "tools", - testonly = 1, - srcs = [ - "ab.go", - "fio.go", - "hey.go", - "iperf.go", - "meminfo.go", - "parser_util.go", - "redis.go", - "sysbench.go", - "tools.go", - ], - visibility = ["//:sandbox"], -) - -go_test( - name = "tools_test", - size = "small", - srcs = [ - "ab_test.go", - "fio_test.go", - "hey_test.go", - "iperf_test.go", - "meminfo_test.go", - "redis_test.go", - "sysbench_test.go", - ], - library = ":tools", -) diff --git a/test/benchmarks/tools/ab.go b/test/benchmarks/tools/ab.go deleted file mode 100644 index d9abf0763..000000000 --- a/test/benchmarks/tools/ab.go +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2020 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" - "net" - "regexp" - "strconv" - "testing" -) - -// ApacheBench is for the client application ApacheBench. -type ApacheBench struct { - Requests int - Concurrency int - Doc string - // TODO(zkoopmans): support KeepAlive and pass option to enable. -} - -// MakeCmd makes an ApacheBench command. -func (a *ApacheBench) MakeCmd(ip net.IP, port int) []string { - path := fmt.Sprintf("http://%s:%d/%s", ip, port, a.Doc) - // See apachebench (ab) for flags. - cmd := fmt.Sprintf("ab -n %d -c %d %s", a.Requests, a.Concurrency, path) - return []string{"sh", "-c", cmd} -} - -// Report parses and reports metrics from ApacheBench output. -func (a *ApacheBench) Report(b *testing.B, output string) { - // Parse and report custom metrics. - transferRate, err := a.parseTransferRate(output) - if err != nil { - b.Logf("failed to parse transferrate: %v", err) - } - b.ReportMetric(transferRate*1024, "transfer_rate_b/s") // Convert from Kb/s to b/s. - ReportCustomMetric(b, transferRate*1024, "transfer_rate" /*metric name*/, "bytes_per_second" /*unit*/) - - latency, err := a.parseLatency(output) - if err != nil { - b.Logf("failed to parse latency: %v", err) - } - b.ReportMetric(latency/1000, "mean_latency_secs") // Convert from ms to s. - ReportCustomMetric(b, latency/1000, "mean_latency" /*metric name*/, "s" /*unit*/) - - reqPerSecond, err := a.parseRequestsPerSecond(output) - if err != nil { - b.Logf("failed to parse requests per second: %v", err) - } - b.ReportMetric(reqPerSecond, "requests_per_second") - ReportCustomMetric(b, reqPerSecond, "requests_per_second" /*metric name*/, "QPS" /*unit*/) -} - -var transferRateRE = regexp.MustCompile(`Transfer rate:\s+(\d+\.?\d+?)\s+\[Kbytes/sec\]\s+received`) - -// parseTransferRate parses transfer rate from ApacheBench output. -func (a *ApacheBench) parseTransferRate(data string) (float64, error) { - match := transferRateRE.FindStringSubmatch(data) - if len(match) < 2 { - return 0, fmt.Errorf("failed get bandwidth: %s", data) - } - return strconv.ParseFloat(match[1], 64) -} - -var latencyRE = regexp.MustCompile(`Total:\s+\d+\s+(\d+)\s+(\d+\.?\d+?)\s+\d+\s+\d+\s`) - -// parseLatency parses latency from ApacheBench output. -func (a *ApacheBench) parseLatency(data string) (float64, error) { - match := latencyRE.FindStringSubmatch(data) - if len(match) < 2 { - return 0, fmt.Errorf("failed get bandwidth: %s", data) - } - return strconv.ParseFloat(match[1], 64) -} - -var requestsPerSecondRE = regexp.MustCompile(`Requests per second:\s+(\d+\.?\d+?)\s+`) - -// parseRequestsPerSecond parses requests per second from ApacheBench output. -func (a *ApacheBench) parseRequestsPerSecond(data string) (float64, error) { - match := requestsPerSecondRE.FindStringSubmatch(data) - if len(match) < 2 { - return 0, fmt.Errorf("failed get bandwidth: %s", data) - } - return strconv.ParseFloat(match[1], 64) -} diff --git a/test/benchmarks/tools/ab_test.go b/test/benchmarks/tools/ab_test.go deleted file mode 100644 index 28ee66ec1..000000000 --- a/test/benchmarks/tools/ab_test.go +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2020 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 "testing" - -// TestApacheBench checks the ApacheBench parsers on sample output. -func TestApacheBench(t *testing.T) { - // Sample output from apachebench. - sampleData := `This is ApacheBench, Version 2.3 <$Revision: 1826891 $> -Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ -Licensed to The Apache Software Foundation, http://www.apache.org/ - -Benchmarking 10.10.10.10 (be patient).....done - - -Server Software: Apache/2.4.38 -Server Hostname: 10.10.10.10 -Server Port: 80 - -Document Path: /latin10k.txt -Document Length: 210 bytes - -Concurrency Level: 1 -Time taken for tests: 0.180 seconds -Complete requests: 100 -Failed requests: 0 -Non-2xx responses: 100 -Total transferred: 38800 bytes -HTML transferred: 21000 bytes -Requests per second: 556.44 [#/sec] (mean) -Time per request: 1.797 [ms] (mean) -Time per request: 1.797 [ms] (mean, across all concurrent requests) -Transfer rate: 210.84 [Kbytes/sec] received - -Connection Times (ms) - min mean[+/-sd] median max -Connect: 0 0 0.2 0 2 -Processing: 1 2 1.0 1 8 -Waiting: 1 1 1.0 1 7 -Total: 1 2 1.2 1 10 - -Percentage of the requests served within a certain time (ms) - 50% 1 - 66% 2 - 75% 2 - 80% 2 - 90% 2 - 95% 3 - 98% 7 - 99% 10 - 100% 10 (longest request)` - - ab := ApacheBench{} - want := 210.84 - got, err := ab.parseTransferRate(sampleData) - if err != nil { - t.Fatalf("failed to parse transfer rate with error: %v", err) - } else if got != want { - t.Fatalf("parseTransferRate got: %f, want: %f", got, want) - } - - want = 2.0 - got, err = ab.parseLatency(sampleData) - if err != nil { - t.Fatalf("failed to parse transfer rate with error: %v", err) - } else if got != want { - t.Fatalf("parseLatency got: %f, want: %f", got, want) - } - - want = 556.44 - got, err = ab.parseRequestsPerSecond(sampleData) - if err != nil { - t.Fatalf("failed to parse transfer rate with error: %v", err) - } else if got != want { - t.Fatalf("parseRequestsPerSecond got: %f, want: %f", got, want) - } -} diff --git a/test/benchmarks/tools/fio.go b/test/benchmarks/tools/fio.go deleted file mode 100644 index f5f60fa84..000000000 --- a/test/benchmarks/tools/fio.go +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright 2020 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 ( - "encoding/json" - "fmt" - "strconv" - "strings" - "testing" -) - -// Fio makes 'fio' commands and parses their output. -type Fio struct { - Test string // test to run: read, write, randread, randwrite. - Size string // total size to be read/written of format N[GMK] (e.g. 5G). - Blocksize string // blocksize to be read/write of format N[GMK] (e.g. 4K). - Iodepth int // iodepth for reads/writes. - Time int // time to run the test in seconds, usually for rand(read/write). -} - -// MakeCmd makes a 'fio' command. -func (f *Fio) MakeCmd(filename string) []string { - cmd := []string{"fio", "--output-format=json", "--ioengine=sync"} - cmd = append(cmd, fmt.Sprintf("--name=%s", f.Test)) - cmd = append(cmd, fmt.Sprintf("--size=%s", f.Size)) - cmd = append(cmd, fmt.Sprintf("--blocksize=%s", f.Blocksize)) - cmd = append(cmd, fmt.Sprintf("--filename=%s", filename)) - cmd = append(cmd, fmt.Sprintf("--iodepth=%d", f.Iodepth)) - cmd = append(cmd, fmt.Sprintf("--rw=%s", f.Test)) - if f.Time != 0 { - cmd = append(cmd, "--time_based") - cmd = append(cmd, fmt.Sprintf("--runtime=%d", f.Time)) - } - return cmd -} - -// Report reports metrics based on output from an 'fio' command. -func (f *Fio) Report(b *testing.B, output string) { - b.Helper() - // Parse the output and report the metrics. - isRead := strings.Contains(f.Test, "read") - bw, err := f.parseBandwidth(output, isRead) - if err != nil { - b.Fatalf("failed to parse bandwidth from %s with: %v", output, err) - } - ReportCustomMetric(b, bw, "bandwidth" /*metric name*/, "bytes_per_second" /*unit*/) - - iops, err := f.parseIOps(output, isRead) - if err != nil { - b.Fatalf("failed to parse iops from %s with: %v", output, err) - } - ReportCustomMetric(b, iops, "io_ops" /*metric name*/, "ops_per_second" /*unit*/) -} - -// parseBandwidth reports the bandwidth in b/s. -func (f *Fio) parseBandwidth(data string, isRead bool) (float64, error) { - if isRead { - result, err := f.parseFioJSON(data, "read", "bw") - if err != nil { - return 0, err - } - return 1024 * result, nil - } - result, err := f.parseFioJSON(data, "write", "bw") - if err != nil { - return 0, err - } - return 1024 * result, nil -} - -// parseIOps reports the write IO per second metric. -func (f *Fio) parseIOps(data string, isRead bool) (float64, error) { - if isRead { - return f.parseFioJSON(data, "read", "iops") - } - return f.parseFioJSON(data, "write", "iops") -} - -// fioResult is for parsing FioJSON. -type fioResult struct { - Jobs []fioJob -} - -// fioJob is for parsing FioJSON. -type fioJob map[string]json.RawMessage - -// fioMetrics is for parsing FioJSON. -type fioMetrics map[string]json.RawMessage - -// parseFioJSON parses data and grabs "op" (read or write) and "metric" -// (bw or iops) from the JSON. -func (f *Fio) parseFioJSON(data, op, metric string) (float64, error) { - var result fioResult - if err := json.Unmarshal([]byte(data), &result); err != nil { - return 0, fmt.Errorf("could not unmarshal data: %v", err) - } - - if len(result.Jobs) < 1 { - return 0, fmt.Errorf("no jobs present to parse") - } - - var metrics fioMetrics - if err := json.Unmarshal(result.Jobs[0][op], &metrics); err != nil { - return 0, fmt.Errorf("could not unmarshal jobs: %v", err) - } - - if _, ok := metrics[metric]; !ok { - return 0, fmt.Errorf("no metric found for op: %s", op) - } - return strconv.ParseFloat(string(metrics[metric]), 64) -} diff --git a/test/benchmarks/tools/fio_test.go b/test/benchmarks/tools/fio_test.go deleted file mode 100644 index a98277150..000000000 --- a/test/benchmarks/tools/fio_test.go +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright 2020 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 "testing" - -// TestFio checks the Fio parsers on sample output. -func TestFio(t *testing.T) { - sampleData := ` -{ - "fio version" : "fio-3.1", - "timestamp" : 1554837456, - "timestamp_ms" : 1554837456621, - "time" : "Tue Apr 9 19:17:36 2019", - "jobs" : [ - { - "jobname" : "test", - "groupid" : 0, - "error" : 0, - "eta" : 2147483647, - "elapsed" : 1, - "job options" : { - "name" : "test", - "ioengine" : "sync", - "size" : "1073741824", - "filename" : "/disk/file.dat", - "iodepth" : "4", - "bs" : "4096", - "rw" : "write" - }, - "read" : { - "io_bytes" : 0, - "io_kbytes" : 0, - "bw" : 123456, - "iops" : 1234.5678, - "runtime" : 0, - "total_ios" : 0, - "short_ios" : 0, - "bw_min" : 0, - "bw_max" : 0, - "bw_agg" : 0.000000, - "bw_mean" : 0.000000, - "bw_dev" : 0.000000, - "bw_samples" : 0, - "iops_min" : 0, - "iops_max" : 0, - "iops_mean" : 0.000000, - "iops_stddev" : 0.000000, - "iops_samples" : 0 - }, - "write" : { - "io_bytes" : 1073741824, - "io_kbytes" : 1048576, - "bw" : 1753471, - "iops" : 438367.892977, - "runtime" : 598, - "total_ios" : 262144, - "bw_min" : 1731120, - "bw_max" : 1731120, - "bw_agg" : 98.725328, - "bw_mean" : 1731120.000000, - "bw_dev" : 0.000000, - "bw_samples" : 1, - "iops_min" : 432780, - "iops_max" : 432780, - "iops_mean" : 432780.000000, - "iops_stddev" : 0.000000, - "iops_samples" : 1 - } - } - ] -} -` - fio := Fio{} - // WriteBandwidth. - got, err := fio.parseBandwidth(sampleData, false) - var want float64 = 1753471.0 * 1024 - if err != nil { - t.Fatalf("parse failed with err: %v", err) - } else if got != want { - t.Fatalf("got: %f, want: %f", got, want) - } - - // ReadBandwidth. - got, err = fio.parseBandwidth(sampleData, true) - want = 123456 * 1024 - if err != nil { - t.Fatalf("parse failed with err: %v", err) - } else if got != want { - t.Fatalf("got: %f, want: %f", got, want) - } - - // WriteIOps. - got, err = fio.parseIOps(sampleData, false) - want = 438367.892977 - if err != nil { - t.Fatalf("parse failed with err: %v", err) - } else if got != want { - t.Fatalf("got: %f, want: %f", got, want) - } - - // ReadIOps. - got, err = fio.parseIOps(sampleData, true) - want = 1234.5678 - if err != nil { - t.Fatalf("parse failed with err: %v", err) - } else if got != want { - t.Fatalf("got: %f, want: %f", got, want) - } -} diff --git a/test/benchmarks/tools/hey.go b/test/benchmarks/tools/hey.go deleted file mode 100644 index b8cb938fe..000000000 --- a/test/benchmarks/tools/hey.go +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2020 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" - "net" - "regexp" - "strconv" - "strings" - "testing" -) - -// Hey is for the client application 'hey'. -type Hey struct { - Requests int // Note: requests cannot be less than concurrency. - Concurrency int - Doc string -} - -// MakeCmd returns a 'hey' command. -func (h *Hey) MakeCmd(ip net.IP, port int) []string { - return strings.Split(fmt.Sprintf("hey -n %d -c %d http://%s:%d/%s", - h.Requests, h.Concurrency, ip, port, h.Doc), " ") -} - -// Report parses output from 'hey' and reports metrics. -func (h *Hey) Report(b *testing.B, output string) { - b.Helper() - requests, err := h.parseRequestsPerSecond(output) - if err != nil { - b.Fatalf("failed to parse requests per second: %v", err) - } - ReportCustomMetric(b, requests, "requests_per_second" /*metric name*/, "QPS" /*unit*/) - - ave, err := h.parseAverageLatency(output) - if err != nil { - b.Fatalf("failed to parse average latency: %v", err) - } - ReportCustomMetric(b, ave, "average_latency" /*metric name*/, "s" /*unit*/) -} - -var heyReqPerSecondRE = regexp.MustCompile(`Requests/sec:\s*(\d+\.?\d+?)\s+`) - -// parseRequestsPerSecond finds requests per second from 'hey' output. -func (h *Hey) parseRequestsPerSecond(data string) (float64, error) { - match := heyReqPerSecondRE.FindStringSubmatch(data) - if len(match) < 2 { - return 0, fmt.Errorf("failed get bandwidth: %s", data) - } - return strconv.ParseFloat(match[1], 64) -} - -var heyAverageLatencyRE = regexp.MustCompile(`Average:\s*(\d+\.?\d+?)\s+secs`) - -// parseHeyAverageLatency finds Average Latency in seconds form 'hey' output. -func (h *Hey) parseAverageLatency(data string) (float64, error) { - match := heyAverageLatencyRE.FindStringSubmatch(data) - if len(match) < 2 { - return 0, fmt.Errorf("failed get average latency match%d : %s", len(match), data) - } - return strconv.ParseFloat(match[1], 64) -} diff --git a/test/benchmarks/tools/hey_test.go b/test/benchmarks/tools/hey_test.go deleted file mode 100644 index e0cab1f52..000000000 --- a/test/benchmarks/tools/hey_test.go +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2020 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 "testing" - -// TestHey checks the Hey parsers on sample output. -func TestHey(t *testing.T) { - sampleData := ` - Summary: - Total: 2.2391 secs - Slowest: 1.6292 secs - Fastest: 0.0066 secs - Average: 0.5351 secs - Requests/sec: 89.3202 - - Total data: 841200 bytes - Size/request: 4206 bytes - - Response time histogram: - 0.007 [1] | - 0.169 [0] | - 0.331 [149] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ - 0.493 [0] | - 0.656 [0] | - 0.818 [0] | - 0.980 [0] | - 1.142 [0] | - 1.305 [0] | - 1.467 [49] |■■■■■■■■■■■■■ - 1.629 [1] | - - - Latency distribution: - 10% in 0.2149 secs - 25% in 0.2449 secs - 50% in 0.2703 secs - 75% in 1.3315 secs - 90% in 1.4045 secs - 95% in 1.4232 secs - 99% in 1.4362 secs - - Details (average, fastest, slowest): - DNS+dialup: 0.0002 secs, 0.0066 secs, 1.6292 secs - DNS-lookup: 0.0000 secs, 0.0000 secs, 0.0000 secs - req write: 0.0000 secs, 0.0000 secs, 0.0012 secs - resp wait: 0.5225 secs, 0.0064 secs, 1.4346 secs - resp read: 0.0122 secs, 0.0001 secs, 0.2006 secs - - Status code distribution: - [200] 200 responses - ` - hey := Hey{} - want := 89.3202 - got, err := hey.parseRequestsPerSecond(sampleData) - if err != nil { - t.Fatalf("failed to parse request per second with: %v", err) - } else if got != want { - t.Fatalf("got: %f, want: %f", got, want) - } - - want = 0.5351 - got, err = hey.parseAverageLatency(sampleData) - if err != nil { - t.Fatalf("failed to parse average latency with: %v", err) - } else if got != want { - t.Fatalf("got: %f, want: %f", got, want) - } -} diff --git a/test/benchmarks/tools/iperf.go b/test/benchmarks/tools/iperf.go deleted file mode 100644 index 5c4e7125b..000000000 --- a/test/benchmarks/tools/iperf.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2020 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" - "net" - "regexp" - "strconv" - "strings" - "testing" -) - -// Iperf is for the client side of `iperf`. -type Iperf struct { - Time int -} - -// MakeCmd returns a iperf client command. -func (i *Iperf) MakeCmd(ip net.IP, port int) []string { - // iperf report in Kb realtime - return strings.Split(fmt.Sprintf("iperf -f K --realtime --time %d -c %s -p %d", i.Time, ip, port), " ") -} - -// Report parses output from iperf client and reports metrics. -func (i *Iperf) Report(b *testing.B, output string) { - b.Helper() - // Parse bandwidth and report it. - bW, err := i.bandwidth(output) - if err != nil { - b.Fatalf("failed to parse bandwitdth from %s: %v", output, err) - } - ReportCustomMetric(b, bW*1024, "bandwidth" /*metric name*/, "bytes_per_second" /*unit*/) -} - -// bandwidth parses the Bandwidth number from an iperf report. A sample is below. -func (i *Iperf) bandwidth(data string) (float64, error) { - re := regexp.MustCompile(`\[\s*\d+\][^\n]+\s+(\d+\.?\d*)\s+KBytes/sec`) - match := re.FindStringSubmatch(data) - if len(match) < 1 { - return 0, fmt.Errorf("failed get bandwidth: %s", data) - } - return strconv.ParseFloat(match[1], 64) -} diff --git a/test/benchmarks/tools/iperf_test.go b/test/benchmarks/tools/iperf_test.go deleted file mode 100644 index 03bb30d05..000000000 --- a/test/benchmarks/tools/iperf_test.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2020 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 "testing" - -// TestIperf checks the Iperf parsers on sample output. -func TestIperf(t *testing.T) { - sampleData := ` ------------------------------------------------------------- -Client connecting to 10.138.15.215, TCP port 32779 -TCP window size: 45.0 KByte (default) ------------------------------------------------------------- -[ 3] local 10.138.15.216 port 32866 connected with 10.138.15.215 port 32779 -[ ID] Interval Transfer Bandwidth -[ 3] 0.0-10.0 sec 459520 KBytes 45900 KBytes/sec -` - i := Iperf{} - bandwidth, err := i.bandwidth(sampleData) - if err != nil || bandwidth != 45900 { - t.Fatalf("failed with: %v and %f", err, bandwidth) - } -} diff --git a/test/benchmarks/tools/meminfo.go b/test/benchmarks/tools/meminfo.go deleted file mode 100644 index b5786fe11..000000000 --- a/test/benchmarks/tools/meminfo.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2020 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" -) - -// Meminfo wraps measurements of MemAvailable using /proc/meminfo. -type Meminfo struct { -} - -// MakeCmd returns a command for checking meminfo. -func (*Meminfo) MakeCmd() (string, []string) { - return "cat", []string{"/proc/meminfo"} -} - -// Report takes two reads of meminfo, parses them, and reports the difference -// divided by b.N. -func (*Meminfo) Report(b *testing.B, before, after string) { - b.Helper() - - beforeVal, err := parseMemAvailable(before) - if err != nil { - b.Fatalf("could not parse before value %s: %v", before, err) - } - - afterVal, err := parseMemAvailable(after) - if err != nil { - b.Fatalf("could not parse before value %s: %v", before, err) - } - val := 1024 * ((beforeVal - afterVal) / float64(b.N)) - ReportCustomMetric(b, val, "average_container_size" /*metric name*/, "bytes" /*units*/) -} - -var memInfoRE = regexp.MustCompile(`MemAvailable:\s*(\d+)\skB\n`) - -// parseMemAvailable grabs the MemAvailable number from /proc/meminfo. -func parseMemAvailable(data string) (float64, error) { - match := memInfoRE.FindStringSubmatch(data) - if len(match) < 2 { - return 0, fmt.Errorf("couldn't find MemAvailable in %s", data) - } - return strconv.ParseFloat(match[1], 64) -} diff --git a/test/benchmarks/tools/meminfo_test.go b/test/benchmarks/tools/meminfo_test.go deleted file mode 100644 index ba803540f..000000000 --- a/test/benchmarks/tools/meminfo_test.go +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2020 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 ( - "testing" -) - -// TestMeminfo checks the Meminfo parser on sample output. -func TestMeminfo(t *testing.T) { - sampleData := ` -MemTotal: 16337408 kB -MemFree: 3742696 kB -MemAvailable: 9319948 kB -Buffers: 1433884 kB -Cached: 4607036 kB -SwapCached: 45284 kB -Active: 8288376 kB -Inactive: 2685928 kB -Active(anon): 4724912 kB -Inactive(anon): 1047940 kB -Active(file): 3563464 kB -Inactive(file): 1637988 kB -Unevictable: 326940 kB -Mlocked: 48 kB -SwapTotal: 33292284 kB -SwapFree: 32865736 kB -Dirty: 708 kB -Writeback: 0 kB -AnonPages: 4304204 kB -Mapped: 975424 kB -Shmem: 910292 kB -KReclaimable: 744532 kB -Slab: 1058448 kB -SReclaimable: 744532 kB -SUnreclaim: 313916 kB -KernelStack: 25188 kB -PageTables: 65300 kB -NFS_Unstable: 0 kB -Bounce: 0 kB -WritebackTmp: 0 kB -CommitLimit: 41460988 kB -Committed_AS: 22859492 kB -VmallocTotal: 34359738367 kB -VmallocUsed: 63088 kB -VmallocChunk: 0 kB -Percpu: 9248 kB -HardwareCorrupted: 0 kB -AnonHugePages: 786432 kB -ShmemHugePages: 0 kB -ShmemPmdMapped: 0 kB -FileHugePages: 0 kB -FilePmdMapped: 0 kB -HugePages_Total: 0 -HugePages_Free: 0 -HugePages_Rsvd: 0 -HugePages_Surp: 0 -Hugepagesize: 2048 kB -Hugetlb: 0 kB -DirectMap4k: 5408532 kB -DirectMap2M: 11241472 kB -DirectMap1G: 1048576 kB -` - want := 9319948.0 - got, err := parseMemAvailable(sampleData) - if err != nil { - t.Fatalf("parseMemAvailable failed: %v", err) - } - if got != want { - t.Fatalf("parseMemAvailable got %f, want %f", got, want) - } -} diff --git a/test/benchmarks/tools/parser_util.go b/test/benchmarks/tools/parser_util.go deleted file mode 100644 index a4555c7dd..000000000 --- a/test/benchmarks/tools/parser_util.go +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2020 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" - "strings" - "testing" -) - -// Parameter is a test parameter. -type Parameter struct { - Name string - Value string -} - -// Output is parsed and split by these values. Make them illegal in input methods. -// We are constrained on what characters these can be by 1) docker's allowable -// container names, 2) golang allowable benchmark names, and 3) golangs allowable -// charecters in b.ReportMetric calls. -var illegalChars = regexp.MustCompile(`[/\.]`) - -// ParametersToName joins parameters into a string format for parsing. -// It is meant to be used for t.Run() calls in benchmark tools. -func ParametersToName(params ...Parameter) (string, error) { - var strs []string - for _, param := range params { - if illegalChars.MatchString(param.Name) || illegalChars.MatchString(param.Value) { - return "", fmt.Errorf("params Name: %q and Value: %q cannot container '.' or '/'", param.Name, param.Value) - } - strs = append(strs, strings.Join([]string{param.Name, param.Value}, ".")) - } - return strings.Join(strs, "/"), nil -} - -// NameToParameters parses the string created by ParametersToName and returns -// it as a set of Parameters. -// Example: BenchmarkRuby/server_threads.1/doc_size.16KB-6 -// The parameter part of this benchmark is: -// "server_threads.1/doc_size.16KB" (BenchmarkRuby is the name, and 6 is GOMAXPROCS) -// This function will return a slice with two parameters -> -// {Name: server_threads, Value: 1}, {Name: doc_size, Value: 16KB} -func NameToParameters(name string) ([]*Parameter, error) { - var params []*Parameter - for _, cond := range strings.Split(name, "/") { - cs := strings.Split(cond, ".") - switch len(cs) { - case 1: - params = append(params, &Parameter{Name: cond, Value: cond}) - case 2: - params = append(params, &Parameter{Name: cs[0], Value: cs[1]}) - default: - return nil, fmt.Errorf("failed to parse param: %s", cond) - } - } - return params, nil -} - -// ReportCustomMetric reports a metric in a set format for parsing. -func ReportCustomMetric(b *testing.B, value float64, name, unit string) { - if illegalChars.MatchString(name) || illegalChars.MatchString(unit) { - b.Fatalf("name: %q and unit: %q cannot contain '/' or '.'", name, unit) - } - nameUnit := strings.Join([]string{name, unit}, ".") - b.ReportMetric(value, nameUnit) -} - -// Metric holds metric data parsed from a string based on the format -// ReportMetric. -type Metric struct { - Name string - Unit string - Sample float64 -} - -// ParseCustomMetric parses a metric reported with ReportCustomMetric. -func ParseCustomMetric(value, metric string) (*Metric, error) { - sample, err := strconv.ParseFloat(value, 64) - if err != nil { - return nil, fmt.Errorf("failed to parse value: %v", err) - } - nameUnit := strings.Split(metric, ".") - if len(nameUnit) != 2 { - return nil, fmt.Errorf("failed to parse metric: %s", metric) - } - return &Metric{Name: nameUnit[0], Unit: nameUnit[1], Sample: sample}, nil -} diff --git a/test/benchmarks/tools/redis.go b/test/benchmarks/tools/redis.go deleted file mode 100644 index e35886437..000000000 --- a/test/benchmarks/tools/redis.go +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2020 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" - "net" - "regexp" - "strconv" - "strings" - "testing" -) - -// Redis is for the client 'redis-benchmark'. -type Redis struct { - Operation string -} - -// MakeCmd returns a redis-benchmark client command. -func (r *Redis) MakeCmd(ip net.IP, port int) []string { - // There is no -t PING_BULK for redis-benchmark, so adjust the command in that case. - // Note that "ping" will run both PING_INLINE and PING_BULK. - if r.Operation == "PING_BULK" { - return strings.Split( - fmt.Sprintf("redis-benchmark --csv -t ping -h %s -p %d", ip, port), " ") - } - - // runs redis-benchmark -t operation for 100K requests against server. - return strings.Split( - fmt.Sprintf("redis-benchmark --csv -t %s -h %s -p %d", r.Operation, ip, port), " ") -} - -// Report parses output from redis-benchmark client and reports metrics. -func (r *Redis) Report(b *testing.B, output string) { - b.Helper() - result, err := r.parseOperation(output) - if err != nil { - b.Fatalf("parsing result %s failed with err: %v", output, err) - } - ReportCustomMetric(b, result, r.Operation /*metric_name*/, "QPS" /*unit*/) -} - -// parseOperation grabs the metric operations per second from redis-benchmark output. -func (r *Redis) parseOperation(data string) (float64, error) { - re := regexp.MustCompile(fmt.Sprintf(`"%s( .*)?","(\d*\.\d*)"`, r.Operation)) - match := re.FindStringSubmatch(data) - if len(match) < 3 { - return 0.0, fmt.Errorf("could not find %s in %s", r.Operation, data) - } - return strconv.ParseFloat(match[2], 64) -} diff --git a/test/benchmarks/tools/redis_test.go b/test/benchmarks/tools/redis_test.go deleted file mode 100644 index 4bafda66f..000000000 --- a/test/benchmarks/tools/redis_test.go +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2020 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 ( - "testing" -) - -// TestRedis checks the Redis parsers on sample output. -func TestRedis(t *testing.T) { - sampleData := ` - "PING_INLINE","48661.80" - "PING_BULK","50301.81" - "SET","48923.68" - "GET","49382.71" - "INCR","49975.02" - "LPUSH","49875.31" - "RPUSH","50276.52" - "LPOP","50327.12" - "RPOP","50556.12" - "SADD","49504.95" - "HSET","49504.95" - "SPOP","50025.02" - "LPUSH (needed to benchmark LRANGE)","48875.86" - "LRANGE_100 (first 100 elements)","33955.86" - "LRANGE_300 (first 300 elements)","16550.81"// Copyright 2020 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 - - "LRANGE_500 (first 450 elements)","13653.74" - "LRANGE_600 (first 600 elements)","11219.57" - "MSET (10 keys)","44682.75" - ` - wants := map[string]float64{ - "PING_INLINE": 48661.80, - "PING_BULK": 50301.81, - "SET": 48923.68, - "GET": 49382.71, - "INCR": 49975.02, - "LPUSH": 49875.31, - "RPUSH": 50276.52, - "LPOP": 50327.12, - "RPOP": 50556.12, - "SADD": 49504.95, - "HSET": 49504.95, - "SPOP": 50025.02, - "LRANGE_100": 33955.86, - "LRANGE_300": 16550.81, - "LRANGE_500": 13653.74, - "LRANGE_600": 11219.57, - "MSET": 44682.75, - } - for op, want := range wants { - redis := Redis{ - Operation: op, - } - if got, err := redis.parseOperation(sampleData); err != nil { - t.Fatalf("failed to parse %s: %v", op, err) - } else if want != got { - t.Fatalf("wanted %f for op %s, got %f", want, op, got) - } - } -} diff --git a/test/benchmarks/tools/sysbench.go b/test/benchmarks/tools/sysbench.go deleted file mode 100644 index 7ccacd8ff..000000000 --- a/test/benchmarks/tools/sysbench.go +++ /dev/null @@ -1,245 +0,0 @@ -// Copyright 2020 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" - "strings" - "testing" -) - -var warmup = "sysbench --threads=8 --memory-total-size=5G memory run > /dev/null &&" - -// Sysbench represents a 'sysbench' command. -type Sysbench interface { - MakeCmd() []string // Makes a sysbench command. - flags() []string - Report(*testing.B, string) // Reports results contained in string. -} - -// SysbenchBase is the top level struct for sysbench and holds top-level arguments -// for sysbench. See: 'sysbench --help' -type SysbenchBase struct { - Threads int // number of Threads for the test. - Time int // time limit for test in seconds. -} - -// baseFlags returns top level flags. -func (s *SysbenchBase) baseFlags() []string { - var ret []string - if s.Threads > 0 { - ret = append(ret, fmt.Sprintf("--threads=%d", s.Threads)) - } - if s.Time > 0 { - ret = append(ret, fmt.Sprintf("--time=%d", s.Time)) - } - return ret -} - -// SysbenchCPU is for 'sysbench [flags] cpu run' and holds CPU specific arguments. -type SysbenchCPU struct { - Base SysbenchBase - MaxPrime int // upper limit for primes generator [10000]. -} - -// MakeCmd makes commands for SysbenchCPU. -func (s *SysbenchCPU) MakeCmd() []string { - cmd := []string{warmup, "sysbench"} - cmd = append(cmd, s.flags()...) - cmd = append(cmd, "cpu run") - return []string{"sh", "-c", strings.Join(cmd, " ")} -} - -// flags makes flags for SysbenchCPU cmds. -func (s *SysbenchCPU) flags() []string { - cmd := s.Base.baseFlags() - if s.MaxPrime > 0 { - return append(cmd, fmt.Sprintf("--cpu-max-prime=%d", s.MaxPrime)) - } - return cmd -} - -// Report reports the relevant metrics for SysbenchCPU. -func (s *SysbenchCPU) Report(b *testing.B, output string) { - b.Helper() - result, err := s.parseEvents(output) - if err != nil { - b.Fatalf("parsing CPU events from %s failed: %v", output, err) - } - ReportCustomMetric(b, result, "cpu_events" /*metric name*/, "events_per_second" /*unit*/) -} - -var cpuEventsPerSecondRE = regexp.MustCompile(`events per second:\s*(\d*.?\d*)\n`) - -// parseEvents parses cpu events per second. -func (s *SysbenchCPU) parseEvents(data string) (float64, error) { - match := cpuEventsPerSecondRE.FindStringSubmatch(data) - if len(match) < 2 { - return 0.0, fmt.Errorf("could not find events per second: %s", data) - } - return strconv.ParseFloat(match[1], 64) -} - -// SysbenchMemory is for 'sysbench [FLAGS] memory run' and holds Memory specific arguments. -type SysbenchMemory struct { - Base SysbenchBase - BlockSize string // size of test memory block [1K]. - TotalSize string // size of data to transfer [100G]. - Scope string // memory access scope {global, local} [global]. - HugeTLB bool // allocate memory from HugeTLB [off]. - OperationType string // type of memory ops {read, write, none} [write]. - AccessMode string // access mode {seq, rnd} [seq]. -} - -// MakeCmd makes commands for SysbenchMemory. -func (s *SysbenchMemory) MakeCmd() []string { - cmd := []string{warmup, "sysbench"} - cmd = append(cmd, s.flags()...) - cmd = append(cmd, "memory run") - return []string{"sh", "-c", strings.Join(cmd, " ")} -} - -// flags makes flags for SysbenchMemory cmds. -func (s *SysbenchMemory) flags() []string { - cmd := s.Base.baseFlags() - if s.BlockSize != "" { - cmd = append(cmd, fmt.Sprintf("--memory-block-size=%s", s.BlockSize)) - } - if s.TotalSize != "" { - cmd = append(cmd, fmt.Sprintf("--memory-total-size=%s", s.TotalSize)) - } - if s.Scope != "" { - cmd = append(cmd, fmt.Sprintf("--memory-scope=%s", s.Scope)) - } - if s.HugeTLB { - cmd = append(cmd, "--memory-hugetlb=on") - } - if s.OperationType != "" { - cmd = append(cmd, fmt.Sprintf("--memory-oper=%s", s.OperationType)) - } - if s.AccessMode != "" { - cmd = append(cmd, fmt.Sprintf("--memory-access-mode=%s", s.AccessMode)) - } - return cmd -} - -// Report reports the relevant metrics for SysbenchMemory. -func (s *SysbenchMemory) Report(b *testing.B, output string) { - b.Helper() - result, err := s.parseOperations(output) - if err != nil { - b.Fatalf("parsing result %s failed with err: %v", output, err) - } - ReportCustomMetric(b, result, "memory_operations" /*metric name*/, "ops_per_second" /*unit*/) -} - -var memoryOperationsRE = regexp.MustCompile(`Total\soperations:\s+\d*\s*\((\d*\.\d*)\sper\ssecond\)`) - -// parseOperations parses memory operations per second form sysbench memory ouput. -func (s *SysbenchMemory) parseOperations(data string) (float64, error) { - match := memoryOperationsRE.FindStringSubmatch(data) - if len(match) < 2 { - return 0.0, fmt.Errorf("couldn't find memory operations per second: %s", data) - } - return strconv.ParseFloat(match[1], 64) -} - -// SysbenchMutex is for 'sysbench [FLAGS] mutex run' and holds Mutex specific arguments. -type SysbenchMutex struct { - Base SysbenchBase - Num int // total size of mutex array [4096]. - Locks int // number of mutex locks per thread [50K]. - Loops int // number of loops to do outside mutex lock [10K]. -} - -// MakeCmd makes commands for SysbenchMutex. -func (s *SysbenchMutex) MakeCmd() []string { - cmd := []string{warmup, "sysbench"} - cmd = append(cmd, s.flags()...) - cmd = append(cmd, "mutex run") - return []string{"sh", "-c", strings.Join(cmd, " ")} -} - -// flags makes flags for SysbenchMutex commands. -func (s *SysbenchMutex) flags() []string { - var cmd []string - cmd = append(cmd, s.Base.baseFlags()...) - if s.Num > 0 { - cmd = append(cmd, fmt.Sprintf("--mutex-num=%d", s.Num)) - } - if s.Locks > 0 { - cmd = append(cmd, fmt.Sprintf("--mutex-locks=%d", s.Locks)) - } - if s.Loops > 0 { - cmd = append(cmd, fmt.Sprintf("--mutex-loops=%d", s.Loops)) - } - return cmd -} - -// Report parses and reports relevant sysbench mutex metrics. -func (s *SysbenchMutex) Report(b *testing.B, output string) { - b.Helper() - - result, err := s.parseExecutionTime(output) - if err != nil { - b.Fatalf("parsing result %s failed with err: %v", output, err) - } - ReportCustomMetric(b, result, "average_execution_time" /*metric name*/, "s" /*unit*/) - - result, err = s.parseDeviation(output) - if err != nil { - b.Fatalf("parsing result %s failed with err: %v", output, err) - } - ReportCustomMetric(b, result, "stddev_execution_time" /*metric name*/, "s" /*unit*/) - - result, err = s.parseLatency(output) - if err != nil { - b.Fatalf("parsing result %s failed with err: %v", output, err) - } - ReportCustomMetric(b, result/1000, "average_latency" /*metric name*/, "s" /*unit*/) -} - -var executionTimeRE = regexp.MustCompile(`execution time \(avg/stddev\):\s*(\d*.?\d*)/(\d*.?\d*)`) - -// parseExecutionTime parses threads fairness average execution time from sysbench output. -func (s *SysbenchMutex) parseExecutionTime(data string) (float64, error) { - match := executionTimeRE.FindStringSubmatch(data) - if len(match) < 2 { - return 0.0, fmt.Errorf("could not find execution time average: %s", data) - } - return strconv.ParseFloat(match[1], 64) -} - -// parseDeviation parses threads fairness stddev time from sysbench output. -func (s *SysbenchMutex) parseDeviation(data string) (float64, error) { - match := executionTimeRE.FindStringSubmatch(data) - if len(match) < 3 { - return 0.0, fmt.Errorf("could not find execution time deviation: %s", data) - } - return strconv.ParseFloat(match[2], 64) -} - -var averageLatencyRE = regexp.MustCompile(`avg:[^\n^\d]*(\d*\.?\d*)`) - -// parseLatency parses latency from sysbench output. -func (s *SysbenchMutex) parseLatency(data string) (float64, error) { - match := averageLatencyRE.FindStringSubmatch(data) - if len(match) < 2 { - return 0.0, fmt.Errorf("could not find average latency: %s", data) - } - return strconv.ParseFloat(match[1], 64) -} diff --git a/test/benchmarks/tools/sysbench_test.go b/test/benchmarks/tools/sysbench_test.go deleted file mode 100644 index 850d1939e..000000000 --- a/test/benchmarks/tools/sysbench_test.go +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright 2020 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 ( - "testing" -) - -// TestSysbenchCpu tests parses on sample 'sysbench cpu' output. -func TestSysbenchCpu(t *testing.T) { - sampleData := ` -sysbench 1.0.11 (using system LuaJIT 2.1.0-beta3) - -Running the test with following options: -Number of threads: 8 -Initializing random number generator from current time - - -Prime numbers limit: 10000 - -Initializing worker threads... - -Threads started! - -CPU speed: - events per second: 9093.38 - -General statistics: - total time: 10.0007s - total number of events: 90949 - -Latency (ms): - min: 0.64 - avg: 0.88 - max: 24.65 - 95th percentile: 1.55 - sum: 79936.91 - -Threads fairness: - events (avg/stddev): 11368.6250/831.38 - execution time (avg/stddev): 9.9921/0.01 -` - sysbench := SysbenchCPU{} - want := 9093.38 - if got, err := sysbench.parseEvents(sampleData); err != nil { - t.Fatalf("parse cpu events failed: %v", err) - } else if want != got { - t.Fatalf("got: %f want: %f", got, want) - } -} - -// TestSysbenchMemory tests parsers on sample 'sysbench memory' output. -func TestSysbenchMemory(t *testing.T) { - sampleData := ` -sysbench 1.0.11 (using system LuaJIT 2.1.0-beta3) - -Running the test with following options: -Number of threads: 8 -Initializing random number generator from current time - - -Running memory speed test with the following options: - block size: 1KiB - total size: 102400MiB - operation: write - scope: global - -Initializing worker threads... - -Threads started! - -Total operations: 47999046 (9597428.64 per second) - -46874.07 MiB transferred (9372.49 MiB/sec) - - -General statistics: - total time: 5.0001s - total number of events: 47999046 - -Latency (ms): - min: 0.00 - avg: 0.00 - max: 0.21 - 95th percentile: 0.00 - sum: 33165.91 - -Threads fairness: - events (avg/stddev): 5999880.7500/111242.52 - execution time (avg/stddev): 4.1457/0.09 -` - sysbench := SysbenchMemory{} - want := 9597428.64 - if got, err := sysbench.parseOperations(sampleData); err != nil { - t.Fatalf("parse memory ops failed: %v", err) - } else if want != got { - t.Fatalf("got: %f want: %f", got, want) - } -} - -// TestSysbenchMutex tests parsers on sample 'sysbench mutex' output. -func TestSysbenchMutex(t *testing.T) { - sampleData := ` -sysbench 1.0.11 (using system LuaJIT 2.1.0-beta3) - -The 'mutex' test requires a command argument. See 'sysbench mutex help' -root@ec078132e294:/# sysbench mutex --threads=8 run -sysbench 1.0.11 (using system LuaJIT 2.1.0-beta3) - -Running the test with following options: -Number of threads: 8 -Initializing random number generator from current time - - -Initializing worker threads... - -Threads started! - - -General statistics: - total time: 0.2320s - total number of events: 8 - -Latency (ms): - min: 152.35 - avg: 192.48 - max: 231.41 - 95th percentile: 231.53 - sum: 1539.83 - -Threads fairness: - events (avg/stddev): 1.0000/0.00 - execution time (avg/stddev): 0.1925/0.04 -` - - sysbench := SysbenchMutex{} - want := .1925 - if got, err := sysbench.parseExecutionTime(sampleData); err != nil { - t.Fatalf("parse mutex time failed: %v", err) - } else if want != got { - t.Fatalf("got: %f want: %f", got, want) - } - - want = 0.04 - if got, err := sysbench.parseDeviation(sampleData); err != nil { - t.Fatalf("parse mutex deviation failed: %v", err) - } else if want != got { - t.Fatalf("got: %f want: %f", got, want) - } - - want = 192.48 - if got, err := sysbench.parseLatency(sampleData); err != nil { - t.Fatalf("parse mutex time failed: %v", err) - } else if want != got { - t.Fatalf("got: %f want: %f", got, want) - } -} diff --git a/test/benchmarks/tools/tools.go b/test/benchmarks/tools/tools.go deleted file mode 100644 index eb61c0136..000000000 --- a/test/benchmarks/tools/tools.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2020 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 holds tooling to couple command formatting and output parsers -// together. -package tools |