Skip to content

Commit b7a2d41

Browse files
committed
testing: print cpu type as label for benchmarks
Supports 386 and amd64 architectures on all operating systems. Example output: $ go test -bench=.* goos: darwin goarch: amd64 pkg: strconv cpu: Intel(R) Core(TM) i7-3520M CPU @ 2.90GHz BenchmarkAtof64Decimal-4 24431032 46.8 ns/op ... As the displayed CPU information is only used for information purposes it is lazily initialized when needed using the new internal/sysinfo package. This allows internal/cpu to stay without dependencies and avoid initialization costs when the CPU information is not needed as the new code to query the CPU name in internal/cpu can be dead code eliminated if not used. Fixes #39214 Change-Id: I77ae5c5d2fed6b28fa78dd45075f9f0a6a7f1bfd Reviewed-on: https://go-review.googlesource.com/c/go/+/263804 Trust: Martin Möhrmann <[email protected]> Reviewed-by: Keith Randall <[email protected]>
1 parent 80182d4 commit b7a2d41

File tree

5 files changed

+111
-1
lines changed

5 files changed

+111
-1
lines changed

src/go/build/deps_test.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,10 @@ var depsRules = `
467467
< net/rpc
468468
< net/rpc/jsonrpc;
469469
470+
# System Information
471+
internal/cpu, sync
472+
< internal/sysinfo;
473+
470474
# Test-only
471475
log
472476
< testing/iotest
@@ -475,7 +479,7 @@ var depsRules = `
475479
FMT, flag, math/rand
476480
< testing/quick;
477481
478-
FMT, flag, runtime/debug, runtime/trace
482+
FMT, flag, runtime/debug, runtime/trace, internal/sysinfo
479483
< testing;
480484
481485
internal/testlog, runtime/pprof, regexp

src/internal/cpu/cpu_no_name.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2020 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// +build !386
6+
// +build !amd64
7+
8+
package cpu
9+
10+
// Name returns the CPU name given by the vendor
11+
// if it can be read directly from memory or by CPU instructions.
12+
// If the CPU name can not be determined an empty string is returned.
13+
//
14+
// Implementations that use the Operating System (e.g. sysctl or /sys/)
15+
// to gather CPU information for display should be placed in internal/sysinfo.
16+
func Name() string {
17+
// "A CPU has no name".
18+
return ""
19+
}

src/internal/cpu/cpu_x86.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ const (
3838
cpuid_ADX = 1 << 19
3939
)
4040

41+
var maxExtendedFunctionInformation uint32
42+
4143
func doinit() {
4244
options = []option{
4345
{Name: "adx", Feature: &X86.HasADX},
@@ -65,6 +67,8 @@ func doinit() {
6567
return
6668
}
6769

70+
maxExtendedFunctionInformation, _, _, _ = cpuid(0x80000000, 0)
71+
6872
_, _, ecx1, edx1 := cpuid(1, 0)
6973
X86.HasSSE2 = isSet(edx1, cpuid_SSE2)
7074

@@ -103,3 +107,48 @@ func doinit() {
103107
func isSet(hwc uint32, value uint32) bool {
104108
return hwc&value != 0
105109
}
110+
111+
// Name returns the CPU name given by the vendor.
112+
// If the CPU name can not be determined an
113+
// empty string is returned.
114+
func Name() string {
115+
if maxExtendedFunctionInformation < 0x80000004 {
116+
return ""
117+
}
118+
119+
data := make([]byte, 0, 3*4*4)
120+
121+
var eax, ebx, ecx, edx uint32
122+
eax, ebx, ecx, edx = cpuid(0x80000002, 0)
123+
data = appendBytes(data, eax, ebx, ecx, edx)
124+
eax, ebx, ecx, edx = cpuid(0x80000003, 0)
125+
data = appendBytes(data, eax, ebx, ecx, edx)
126+
eax, ebx, ecx, edx = cpuid(0x80000004, 0)
127+
data = appendBytes(data, eax, ebx, ecx, edx)
128+
129+
// Trim leading spaces.
130+
for len(data) > 0 && data[0] == ' ' {
131+
data = data[1:]
132+
}
133+
134+
// Trim tail after and including the first null byte.
135+
for i, c := range data {
136+
if c == '\x00' {
137+
data = data[:i]
138+
break
139+
}
140+
}
141+
142+
return string(data)
143+
}
144+
145+
func appendBytes(b []byte, args ...uint32) []byte {
146+
for _, arg := range args {
147+
b = append(b,
148+
byte((arg >> 0)),
149+
byte((arg >> 8)),
150+
byte((arg >> 16)),
151+
byte((arg >> 24)))
152+
}
153+
return b
154+
}

src/internal/sysinfo/sysinfo.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright 2020 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// Package sysinfo implements high level hardware information gathering
6+
// that can be used for debugging or information purposes.
7+
package sysinfo
8+
9+
import (
10+
internalcpu "internal/cpu"
11+
"sync"
12+
)
13+
14+
type cpuInfo struct {
15+
once sync.Once
16+
name string
17+
}
18+
19+
var CPU cpuInfo
20+
21+
func (cpu *cpuInfo) Name() string {
22+
cpu.once.Do(func() {
23+
// Try to get the information from internal/cpu.
24+
if name := internalcpu.Name(); name != "" {
25+
cpu.name = name
26+
return
27+
}
28+
// TODO(martisch): use /proc/cpuinfo and /sys/devices/system/cpu/ on Linux as fallback.
29+
})
30+
return cpu.name
31+
}

src/testing/benchmark.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"flag"
99
"fmt"
1010
"internal/race"
11+
"internal/sysinfo"
1112
"io"
1213
"math"
1314
"os"
@@ -262,6 +263,9 @@ func (b *B) run() {
262263
if b.importPath != "" {
263264
fmt.Fprintf(b.w, "pkg: %s\n", b.importPath)
264265
}
266+
if cpu := sysinfo.CPU.Name(); cpu != "" {
267+
fmt.Fprintf(b.w, "cpu: %s\n", cpu)
268+
}
265269
})
266270
if b.context != nil {
267271
// Running go test --test.bench
@@ -648,6 +652,9 @@ func (b *B) Run(name string, f func(b *B)) bool {
648652
if b.importPath != "" {
649653
fmt.Printf("pkg: %s\n", b.importPath)
650654
}
655+
if cpu := sysinfo.CPU.Name(); cpu != "" {
656+
fmt.Printf("cpu: %s\n", cpu)
657+
}
651658
})
652659

653660
fmt.Println(benchName)

0 commit comments

Comments
 (0)