github.com/jgbaldwinbrown/perf@v0.1.1/benchstat/scaler.go (about)

     1  // Copyright 2017 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 benchstat
     6  
     7  import (
     8  	"fmt"
     9  	"strings"
    10  )
    11  
    12  // A Scaler is a function that scales and formats a measurement.
    13  // All measurements within a given table row are formatted
    14  // using the same scaler, so that the units are consistent
    15  // across the row.
    16  type Scaler func(float64) string
    17  
    18  // NewScaler returns a Scaler appropriate for formatting
    19  // the measurement val, which has the given unit.
    20  func NewScaler(val float64, unit string) Scaler {
    21  	if hasBaseUnit(unit, "ns/op") || hasBaseUnit(unit, "ns/GC") {
    22  		return timeScaler(val)
    23  	}
    24  
    25  	var format string
    26  	var scale float64
    27  	var suffix string
    28  
    29  	prescale := 1.0
    30  	if hasBaseUnit(unit, "MB/s") {
    31  		prescale = 1e6
    32  	}
    33  
    34  	switch x := val * prescale; {
    35  	case x >= 99500000000000:
    36  		format, scale, suffix = "%.0f", 1e12, "T"
    37  	case x >= 9950000000000:
    38  		format, scale, suffix = "%.1f", 1e12, "T"
    39  	case x >= 995000000000:
    40  		format, scale, suffix = "%.2f", 1e12, "T"
    41  	case x >= 99500000000:
    42  		format, scale, suffix = "%.0f", 1e9, "G"
    43  	case x >= 9950000000:
    44  		format, scale, suffix = "%.1f", 1e9, "G"
    45  	case x >= 995000000:
    46  		format, scale, suffix = "%.2f", 1e9, "G"
    47  	case x >= 99500000:
    48  		format, scale, suffix = "%.0f", 1e6, "M"
    49  	case x >= 9950000:
    50  		format, scale, suffix = "%.1f", 1e6, "M"
    51  	case x >= 995000:
    52  		format, scale, suffix = "%.2f", 1e6, "M"
    53  	case x >= 99500:
    54  		format, scale, suffix = "%.0f", 1e3, "k"
    55  	case x >= 9950:
    56  		format, scale, suffix = "%.1f", 1e3, "k"
    57  	case x >= 995:
    58  		format, scale, suffix = "%.2f", 1e3, "k"
    59  	case x >= 99.5:
    60  		format, scale, suffix = "%.0f", 1, ""
    61  	case x >= 9.95:
    62  		format, scale, suffix = "%.1f", 1, ""
    63  	default:
    64  		format, scale, suffix = "%.2f", 1, ""
    65  	}
    66  
    67  	if hasBaseUnit(unit, "B/op") || hasBaseUnit(unit, "bytes/op") || hasBaseUnit(unit, "bytes") {
    68  		suffix += "B"
    69  	}
    70  	if hasBaseUnit(unit, "MB/s") {
    71  		suffix += "B/s"
    72  	}
    73  	scale /= prescale
    74  
    75  	return func(val float64) string {
    76  		return fmt.Sprintf(format+suffix, val/scale)
    77  	}
    78  }
    79  
    80  func timeScaler(ns float64) Scaler {
    81  	var format string
    82  	var scale float64
    83  	switch x := ns / 1e9; {
    84  	case x >= 99.5:
    85  		format, scale = "%.0fs", 1
    86  	case x >= 9.95:
    87  		format, scale = "%.1fs", 1
    88  	case x >= 0.995:
    89  		format, scale = "%.2fs", 1
    90  	case x >= 0.0995:
    91  		format, scale = "%.0fms", 1000
    92  	case x >= 0.00995:
    93  		format, scale = "%.1fms", 1000
    94  	case x >= 0.000995:
    95  		format, scale = "%.2fms", 1000
    96  	case x >= 0.0000995:
    97  		format, scale = "%.0fµs", 1000*1000
    98  	case x >= 0.00000995:
    99  		format, scale = "%.1fµs", 1000*1000
   100  	case x >= 0.000000995:
   101  		format, scale = "%.2fµs", 1000*1000
   102  	case x >= 0.0000000995:
   103  		format, scale = "%.0fns", 1000*1000*1000
   104  	case x >= 0.00000000995:
   105  		format, scale = "%.1fns", 1000*1000*1000
   106  	default:
   107  		format, scale = "%.2fns", 1000*1000*1000
   108  	}
   109  	return func(ns float64) string {
   110  		return fmt.Sprintf(format, ns/1e9*scale)
   111  	}
   112  }
   113  
   114  // hasBaseUnit reports whether s has unit unit.
   115  // For now, it reports whether s == unit or s ends in -unit.
   116  func hasBaseUnit(s, unit string) bool {
   117  	return s == unit || strings.HasSuffix(s, "-"+unit)
   118  }