mirror of
https://github.com/golang/go.git
synced 2025-05-28 10:51:22 +00:00
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/jsonrpc;
|
||||
|
||||
# System Information
|
||||
internal/cpu, sync
|
||||
< internal/sysinfo;
|
||||
|
||||
# Test-only
|
||||
log
|
||||
< testing/iotest
|
||||
@ -475,7 +479,7 @@ var depsRules = `
|
||||
FMT, flag, math/rand
|
||||
< testing/quick;
|
||||
|
||||
FMT, flag, runtime/debug, runtime/trace
|
||||
FMT, flag, runtime/debug, runtime/trace, internal/sysinfo
|
||||
< testing;
|
||||
|
||||
internal/testlog, runtime/pprof, regexp
|
||||
|
19
src/internal/cpu/cpu_no_name.go
Normal file
19
src/internal/cpu/cpu_no_name.go
Normal file
@ -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
|
||||
)
|
||||
|
||||
var maxExtendedFunctionInformation uint32
|
||||
|
||||
func doinit() {
|
||||
options = []option{
|
||||
{Name: "adx", Feature: &X86.HasADX},
|
||||
@ -65,6 +67,8 @@ func doinit() {
|
||||
return
|
||||
}
|
||||
|
||||
maxExtendedFunctionInformation, _, _, _ = cpuid(0x80000000, 0)
|
||||
|
||||
_, _, ecx1, edx1 := cpuid(1, 0)
|
||||
X86.HasSSE2 = isSet(edx1, cpuid_SSE2)
|
||||
|
||||
@ -103,3 +107,48 @@ func doinit() {
|
||||
func isSet(hwc uint32, value uint32) bool {
|
||||
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
|
||||
}
|
||||
|
31
src/internal/sysinfo/sysinfo.go
Normal file
31
src/internal/sysinfo/sysinfo.go
Normal file
@ -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"
|
||||
"fmt"
|
||||
"internal/race"
|
||||
"internal/sysinfo"
|
||||
"io"
|
||||
"math"
|
||||
"os"
|
||||
@ -262,6 +263,9 @@ func (b *B) run() {
|
||||
if 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 {
|
||||
// Running go test --test.bench
|
||||
@ -648,6 +652,9 @@ func (b *B) Run(name string, f func(b *B)) bool {
|
||||
if b.importPath != "" {
|
||||
fmt.Printf("pkg: %s\n", b.importPath)
|
||||
}
|
||||
if cpu := sysinfo.CPU.Name(); cpu != "" {
|
||||
fmt.Printf("cpu: %s\n", cpu)
|
||||
}
|
||||
})
|
||||
|
||||
fmt.Println(benchName)
|
||||
|
Loading…
x
Reference in New Issue
Block a user