mirror of https://github.com/golang/go.git
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 <moehrmann@google.com> Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
parent
80182d45b5
commit
b7a2d413a3
|
|
@ -467,6 +467,10 @@ var depsRules = `
|
||||||
< net/rpc
|
< net/rpc
|
||||||
< net/rpc/jsonrpc;
|
< net/rpc/jsonrpc;
|
||||||
|
|
||||||
|
# System Information
|
||||||
|
internal/cpu, sync
|
||||||
|
< internal/sysinfo;
|
||||||
|
|
||||||
# Test-only
|
# Test-only
|
||||||
log
|
log
|
||||||
< testing/iotest
|
< testing/iotest
|
||||||
|
|
@ -475,7 +479,7 @@ var depsRules = `
|
||||||
FMT, flag, math/rand
|
FMT, flag, math/rand
|
||||||
< testing/quick;
|
< testing/quick;
|
||||||
|
|
||||||
FMT, flag, runtime/debug, runtime/trace
|
FMT, flag, runtime/debug, runtime/trace, internal/sysinfo
|
||||||
< testing;
|
< testing;
|
||||||
|
|
||||||
internal/testlog, runtime/pprof, regexp
|
internal/testlog, runtime/pprof, regexp
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
// Copyright 2020 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.
|
||||||
|
|
||||||
|
// +build !386
|
||||||
|
// +build !amd64
|
||||||
|
|
||||||
|
package cpu
|
||||||
|
|
||||||
|
// Name returns the CPU name given by the vendor
|
||||||
|
// if it can be read directly from memory or by CPU instructions.
|
||||||
|
// If the CPU name can not be determined an empty string is returned.
|
||||||
|
//
|
||||||
|
// Implementations that use the Operating System (e.g. sysctl or /sys/)
|
||||||
|
// to gather CPU information for display should be placed in internal/sysinfo.
|
||||||
|
func Name() string {
|
||||||
|
// "A CPU has no name".
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
@ -38,6 +38,8 @@ const (
|
||||||
cpuid_ADX = 1 << 19
|
cpuid_ADX = 1 << 19
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var maxExtendedFunctionInformation uint32
|
||||||
|
|
||||||
func doinit() {
|
func doinit() {
|
||||||
options = []option{
|
options = []option{
|
||||||
{Name: "adx", Feature: &X86.HasADX},
|
{Name: "adx", Feature: &X86.HasADX},
|
||||||
|
|
@ -65,6 +67,8 @@ func doinit() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
maxExtendedFunctionInformation, _, _, _ = cpuid(0x80000000, 0)
|
||||||
|
|
||||||
_, _, ecx1, edx1 := cpuid(1, 0)
|
_, _, ecx1, edx1 := cpuid(1, 0)
|
||||||
X86.HasSSE2 = isSet(edx1, cpuid_SSE2)
|
X86.HasSSE2 = isSet(edx1, cpuid_SSE2)
|
||||||
|
|
||||||
|
|
@ -103,3 +107,48 @@ func doinit() {
|
||||||
func isSet(hwc uint32, value uint32) bool {
|
func isSet(hwc uint32, value uint32) bool {
|
||||||
return hwc&value != 0
|
return hwc&value != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Name returns the CPU name given by the vendor.
|
||||||
|
// If the CPU name can not be determined an
|
||||||
|
// empty string is returned.
|
||||||
|
func Name() string {
|
||||||
|
if maxExtendedFunctionInformation < 0x80000004 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
data := make([]byte, 0, 3*4*4)
|
||||||
|
|
||||||
|
var eax, ebx, ecx, edx uint32
|
||||||
|
eax, ebx, ecx, edx = cpuid(0x80000002, 0)
|
||||||
|
data = appendBytes(data, eax, ebx, ecx, edx)
|
||||||
|
eax, ebx, ecx, edx = cpuid(0x80000003, 0)
|
||||||
|
data = appendBytes(data, eax, ebx, ecx, edx)
|
||||||
|
eax, ebx, ecx, edx = cpuid(0x80000004, 0)
|
||||||
|
data = appendBytes(data, eax, ebx, ecx, edx)
|
||||||
|
|
||||||
|
// Trim leading spaces.
|
||||||
|
for len(data) > 0 && data[0] == ' ' {
|
||||||
|
data = data[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trim tail after and including the first null byte.
|
||||||
|
for i, c := range data {
|
||||||
|
if c == '\x00' {
|
||||||
|
data = data[:i]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func appendBytes(b []byte, args ...uint32) []byte {
|
||||||
|
for _, arg := range args {
|
||||||
|
b = append(b,
|
||||||
|
byte((arg >> 0)),
|
||||||
|
byte((arg >> 8)),
|
||||||
|
byte((arg >> 16)),
|
||||||
|
byte((arg >> 24)))
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
// Copyright 2020 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 sysinfo implements high level hardware information gathering
|
||||||
|
// that can be used for debugging or information purposes.
|
||||||
|
package sysinfo
|
||||||
|
|
||||||
|
import (
|
||||||
|
internalcpu "internal/cpu"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type cpuInfo struct {
|
||||||
|
once sync.Once
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
var CPU cpuInfo
|
||||||
|
|
||||||
|
func (cpu *cpuInfo) Name() string {
|
||||||
|
cpu.once.Do(func() {
|
||||||
|
// Try to get the information from internal/cpu.
|
||||||
|
if name := internalcpu.Name(); name != "" {
|
||||||
|
cpu.name = name
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// TODO(martisch): use /proc/cpuinfo and /sys/devices/system/cpu/ on Linux as fallback.
|
||||||
|
})
|
||||||
|
return cpu.name
|
||||||
|
}
|
||||||
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"internal/race"
|
"internal/race"
|
||||||
|
"internal/sysinfo"
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
"os"
|
"os"
|
||||||
|
|
@ -262,6 +263,9 @@ func (b *B) run() {
|
||||||
if b.importPath != "" {
|
if b.importPath != "" {
|
||||||
fmt.Fprintf(b.w, "pkg: %s\n", b.importPath)
|
fmt.Fprintf(b.w, "pkg: %s\n", b.importPath)
|
||||||
}
|
}
|
||||||
|
if cpu := sysinfo.CPU.Name(); cpu != "" {
|
||||||
|
fmt.Fprintf(b.w, "cpu: %s\n", cpu)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
if b.context != nil {
|
if b.context != nil {
|
||||||
// Running go test --test.bench
|
// Running go test --test.bench
|
||||||
|
|
@ -648,6 +652,9 @@ func (b *B) Run(name string, f func(b *B)) bool {
|
||||||
if b.importPath != "" {
|
if b.importPath != "" {
|
||||||
fmt.Printf("pkg: %s\n", b.importPath)
|
fmt.Printf("pkg: %s\n", b.importPath)
|
||||||
}
|
}
|
||||||
|
if cpu := sysinfo.CPU.Name(); cpu != "" {
|
||||||
|
fmt.Printf("cpu: %s\n", cpu)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
fmt.Println(benchName)
|
fmt.Println(benchName)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue