driver: fix build on Plan 9
Added missing functions on Plan 9. The "peak-RSS-bytes" metrics has been
left out because there doesn't seem to be an easy way to compute it on
Plan 9.
Fixes golang/go#35885
Change-Id: I111e9b5757b37f7e3479330727267947055180a6
Reviewed-on: https://go-review.googlesource.com/c/benchmarks/+/209224
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Tobias Klauser <tobias.klauser@gmail.com>
diff --git a/driver/driver_plan9.go b/driver/driver_plan9.go
new file mode 100644
index 0000000..2b58d8a
--- /dev/null
+++ b/driver/driver_plan9.go
@@ -0,0 +1,102 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package driver
+
+import (
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "os/exec"
+ "strconv"
+ "strings"
+ "syscall"
+ "time"
+)
+
+func RunUnderProfiler(args ...string) (string, string) {
+ return "", ""
+}
+
+// Size runs size command on the file. Returns filename with output. Any errors are ignored.
+func Size(file string) string {
+ return ""
+}
+
+type sysStats struct {
+ N uint64
+ CPUTime uint64
+}
+
+func InitSysStats(N uint64) sysStats {
+ ss := sysStats{N: N}
+ var err error
+ ss.CPUTime, err = procCPUTime()
+ if err != nil {
+ log.Printf("failed to parse /dev/cputime: %v", err)
+ ss.N = 0
+ // Deliberately ignore the error.
+ }
+ return ss
+}
+
+func (ss sysStats) Collect(res *Result) {
+ if ss.N == 0 {
+ return
+ }
+ t, err := procCPUTime()
+ if err != nil {
+ log.Printf("failed to parse /dev/cputime: %v", err)
+ // Deliberately ignore the error.
+ return
+ }
+ res.Metrics["user+sys-ns/op"] = (t - ss.CPUTime) / ss.N
+}
+
+func RunAndCollectSysStats(cmd *exec.Cmd, res *Result, N uint64, prefix string) (string, error) {
+ var out bytes.Buffer
+ cmd.Stdout = &out
+ cmd.Stderr = &out
+ t0 := time.Now()
+ if err := cmd.Run(); err != nil {
+ return out.String(), err
+ }
+ t1 := time.Now()
+ w := cmd.ProcessState.SysUsage().(*syscall.Waitmsg)
+ res.RunTime = uint64(t1.Sub(t0)) / N
+ res.Metrics[prefix+"ns/op"] = res.RunTime
+ res.Metrics[prefix+"user+sys-ns/op"] = cpuTime(w) / N
+ return out.String(), nil
+}
+
+func procCPUTime() (uint64, error) {
+ b, err := ioutil.ReadFile("/dev/cputime")
+ if err != nil {
+ return 0, err
+ }
+ f := strings.Fields(string(b))
+ if n := len(f); n != 6 {
+ return 0, fmt.Errorf("/dev/cputime has %v fields", n)
+ }
+
+ // Sum up time spent in user mode and system calls,
+ // for both the current process and the descendants.
+ var tt uint64
+ for _, i := range []int{0, 1, 3, 4} {
+ t, err := strconv.ParseUint(f[i], 10, 32)
+ if err != nil {
+ return 0, err
+ }
+ tt += t
+ }
+ return tt * 1e6, nil
+}
+
+func cpuTime(w *syscall.Waitmsg) uint64 {
+ return uint64(w.Time[0])*1e6 + uint64(w.Time[1])*1e6
+}
+
+func setProcessAffinity(v int) {
+}