github.com/flyinox/gosm@v0.0.0-20171117061539-16768cb62077/src/math/big/calibrate_test.go (about)

     1  // Copyright 2009 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  // This file prints execution times for the Mul benchmark
     6  // given different Karatsuba thresholds. The result may be
     7  // used to manually fine-tune the threshold constant. The
     8  // results are somewhat fragile; use repeated runs to get
     9  // a clear picture.
    10  
    11  // Usage: go test -run=TestCalibrate -calibrate
    12  
    13  package big
    14  
    15  import (
    16  	"flag"
    17  	"fmt"
    18  	"testing"
    19  	"time"
    20  )
    21  
    22  var calibrate = flag.Bool("calibrate", false, "run calibration test")
    23  
    24  func karatsubaLoad(b *testing.B) {
    25  	BenchmarkMul(b)
    26  }
    27  
    28  // measureKaratsuba returns the time to run a Karatsuba-relevant benchmark
    29  // given Karatsuba threshold th.
    30  func measureKaratsuba(th int) time.Duration {
    31  	th, karatsubaThreshold = karatsubaThreshold, th
    32  	res := testing.Benchmark(karatsubaLoad)
    33  	karatsubaThreshold = th
    34  	return time.Duration(res.NsPerOp())
    35  }
    36  
    37  func computeThresholds() {
    38  	fmt.Printf("Multiplication times for varying Karatsuba thresholds\n")
    39  	fmt.Printf("(run repeatedly for good results)\n")
    40  
    41  	// determine Tk, the work load execution time using basic multiplication
    42  	Tb := measureKaratsuba(1e9) // th == 1e9 => Karatsuba multiplication disabled
    43  	fmt.Printf("Tb = %10s\n", Tb)
    44  
    45  	// thresholds
    46  	th := 4
    47  	th1 := -1
    48  	th2 := -1
    49  
    50  	var deltaOld time.Duration
    51  	for count := -1; count != 0 && th < 128; count-- {
    52  		// determine Tk, the work load execution time using Karatsuba multiplication
    53  		Tk := measureKaratsuba(th)
    54  
    55  		// improvement over Tb
    56  		delta := (Tb - Tk) * 100 / Tb
    57  
    58  		fmt.Printf("th = %3d  Tk = %10s  %4d%%", th, Tk, delta)
    59  
    60  		// determine break-even point
    61  		if Tk < Tb && th1 < 0 {
    62  			th1 = th
    63  			fmt.Print("  break-even point")
    64  		}
    65  
    66  		// determine diminishing return
    67  		if 0 < delta && delta < deltaOld && th2 < 0 {
    68  			th2 = th
    69  			fmt.Print("  diminishing return")
    70  		}
    71  		deltaOld = delta
    72  
    73  		fmt.Println()
    74  
    75  		// trigger counter
    76  		if th1 >= 0 && th2 >= 0 && count < 0 {
    77  			count = 10 // this many extra measurements after we got both thresholds
    78  		}
    79  
    80  		th++
    81  	}
    82  }
    83  
    84  func TestCalibrate(t *testing.T) {
    85  	if *calibrate {
    86  		computeThresholds()
    87  	}
    88  }