github.com/jgbaldwinbrown/perf@v0.1.1/benchfmt/units.go (about) 1 // Copyright 2022 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 benchfmt 6 7 import ( 8 "golang.org/x/perf/benchmath" 9 "golang.org/x/perf/benchunit" 10 ) 11 12 // Unit metadata is a single piece of unit metadata. 13 // 14 // Unit metadata gives information that's useful to interpreting 15 // values in a given unit. The following metadata keys are predefined: 16 // 17 // better={higher,lower} indicates whether higher or lower values of 18 // this unit are better (indicate an improvement). 19 // 20 // assume={nothing,exact} indicates what statistical assumption to 21 // make when considering distributions of values. 22 // `nothing` means to make no statistical assumptions (e.g., use 23 // non-parametric methods) and `exact` means to assume measurements are 24 // exact (repeated measurement does not increase confidence). 25 // The default is `nothing`. 26 type UnitMetadata struct { 27 UnitMetadataKey 28 29 // OrigUnit is the original, untidied unit as written in the input. 30 OrigUnit string 31 32 Value string 33 34 fileName string 35 line int 36 } 37 38 func (u *UnitMetadata) Pos() (fileName string, line int) { 39 return u.fileName, u.line 40 } 41 42 // UnitMetadataKey identifies a single piece of unit metadata by unit 43 // and metadata name. 44 type UnitMetadataKey struct { 45 Unit string 46 Key string // Metadata key (e.g., "better" or "assume") 47 } 48 49 // UnitMetadataMap stores the accumulated metadata for several units. 50 // This is indexed by tidied units, while the values store the original 51 // units from the benchmark file. 52 type UnitMetadataMap map[UnitMetadataKey]*UnitMetadata 53 54 // Get returns the unit metadata for the specified unit and metadata key. 55 // It tidies unit if necessary. 56 func (m UnitMetadataMap) Get(unit, key string) *UnitMetadata { 57 _, tidyUnit := benchunit.Tidy(1, unit) 58 return m[UnitMetadataKey{tidyUnit, key}] 59 } 60 61 // GetAssumption returns the appropriate statistical Assumption to make 62 // about distributions of values in the given unit. 63 func (m UnitMetadataMap) GetAssumption(unit string) benchmath.Assumption { 64 dist := m.Get(unit, "assume") 65 if dist != nil && dist.Value == "exact" { 66 return benchmath.AssumeExact 67 } 68 // The default is to assume nothing. 69 return benchmath.AssumeNothing 70 } 71 72 // GetBetter returns whether higher or lower values of the given unit 73 // indicate an improvement. It returns +1 if higher values are better, 74 // -1 if lower values are better, or 0 if unknown. 75 func (m UnitMetadataMap) GetBetter(unit string) int { 76 better := m.Get(unit, "better") 77 if better != nil { 78 switch better.Value { 79 case "higher": 80 return 1 81 case "lower": 82 return -1 83 } 84 return 0 85 } 86 // Fall back to some built-in defaults. 87 switch unit { 88 case "ns/op", "sec/op": 89 // This measures "duration", so lower is better. 90 return -1 91 case "MB/s", "B/s": 92 // This measures "speed", so higher is better. 93 return 1 94 case "B/op", "allocs/op": 95 // These measure amount of allocation, so lower is better. 96 return -1 97 } 98 return 0 99 }