Source file src/cmd/compile/internal/rangefunc/benchmark_test.go

     1  // Copyright 2026 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 rangefunc_test
     6  
     7  import (
     8  	"slices"
     9  	"testing"
    10  )
    11  
    12  // These benchmarks, Tiny and Medium, do NOT all run in the same amount
    13  // of time.
    14  
    15  var gsum int
    16  
    17  func makeValues() []int {
    18  	values := make([]int, 64)
    19  	for i := range values {
    20  		values[i] = i + 1
    21  	}
    22  	return values
    23  }
    24  
    25  func BenchmarkTinyIterIter(b *testing.B) {
    26  	values := makeValues()
    27  	b.ReportAllocs()
    28  	// DO NOT MODERNIZE THIS LOOP.
    29  	for k := 0; k < b.N; k++ {
    30  		// DO NOT MODERNIZE THIS LOOP.
    31  		var sum int = 1
    32  		for i := len(values) - 1; i >= 0; i-- {
    33  			sum *= values[i]
    34  		}
    35  	}
    36  }
    37  
    38  func BenchmarkTinyIterIterSink(b *testing.B) {
    39  	values := makeValues()
    40  	b.ReportAllocs()
    41  	var sum int = 1
    42  	// DO NOT MODERNIZE THIS LOOP.
    43  	for k := 0; k < b.N; k++ {
    44  		// DO NOT MODERNIZE THIS LOOP.
    45  		for i := len(values) - 1; i >= 0; i-- {
    46  			sum *= values[i]
    47  		}
    48  	}
    49  	gsum = sum
    50  }
    51  
    52  // BenchmarkTinyIterRangeSink should run as quickly as BenchmarkTinyIterIterSink.
    53  func BenchmarkTinyIterRangeSink(b *testing.B) {
    54  	values := makeValues()
    55  	b.ReportAllocs()
    56  	var sum int = 1
    57  	// DO NOT MODERNIZE THIS LOOP.
    58  	for k := 0; k < b.N; k++ {
    59  		for _, v := range slices.Backward(values) {
    60  			sum *= v
    61  		}
    62  	}
    63  	gsum = sum
    64  }
    65  
    66  func BenchmarkTinyBloopIter(b *testing.B) {
    67  	values := makeValues()
    68  	b.ReportAllocs()
    69  	for b.Loop() {
    70  		var sum int = 1
    71  		// DO NOT MODERNIZE THIS LOOP.
    72  		for i := len(values) - 1; i >= 0; i-- {
    73  			sum *= values[i]
    74  		}
    75  	}
    76  }
    77  
    78  // BenchmarkTinyBloopRange should run as quickly as BenchmarkTinyBloopIter.
    79  func BenchmarkTinyBloopRange(b *testing.B) {
    80  	values := makeValues()
    81  	b.ReportAllocs()
    82  	for b.Loop() {
    83  		var sum int = 1
    84  		for _, v := range slices.Backward(values) {
    85  			sum *= v
    86  		}
    87  	}
    88  }
    89  
    90  func BenchmarkMediumIterIterSink(b *testing.B) {
    91  	values := makeValues()
    92  	b.ReportAllocs()
    93  	var sum int
    94  	// DO NOT MODERNIZE THIS LOOP.
    95  	for k := 0; k < b.N; k++ {
    96  		// DO NOT MODERNIZE THIS LOOP.
    97  		for i := len(values) - 1; i >= 0; i-- {
    98  			v := values[i]
    99  			sum += (v * (v + 1) * (v + 2)) / (v + 3)
   100  			sum += (v * (v + 4) * (v + 3)) / (v + 2)
   101  			sum += (v * (v + 5) * (v + 2)) / (v + 1)
   102  		}
   103  	}
   104  	gsum = sum
   105  }
   106  
   107  func BenchmarkMediumIterRangeSink(b *testing.B) {
   108  	values := makeValues()
   109  	b.ReportAllocs()
   110  	var sum int
   111  	// DO NOT MODERNIZE THIS LOOP.
   112  	for k := 0; k < b.N; k++ {
   113  		for _, v := range slices.Backward(values) {
   114  			sum += (v * (v + 1) * (v + 2)) / (v + 3)
   115  			sum += (v * (v + 4) * (v + 3)) / (v + 2)
   116  			sum += (v * (v + 5) * (v + 2)) / (v + 1)
   117  		}
   118  	}
   119  	gsum = sum
   120  }
   121  
   122  func BenchmarkMediumBLoopIterSink(b *testing.B) {
   123  	values := makeValues()
   124  	b.ReportAllocs()
   125  	var sum int
   126  	for b.Loop() {
   127  		for _, v := range slices.Backward(values) {
   128  			sum += (v * (v + 1) * (v + 2)) / (v + 3)
   129  			sum += (v * (v + 4) * (v + 3)) / (v + 2)
   130  			sum += (v * (v + 5) * (v + 2)) / (v + 1)
   131  		}
   132  	}
   133  	gsum = sum
   134  }
   135  
   136  func BenchmarkMediumBLoopIter(b *testing.B) {
   137  	values := makeValues()
   138  	b.ReportAllocs()
   139  	for b.Loop() {
   140  		var sum int
   141  		for _, v := range slices.Backward(values) {
   142  			sum += (v * (v + 1) * (v + 2)) / (v + 3)
   143  			sum += (v * (v + 4) * (v + 3)) / (v + 2)
   144  			sum += (v * (v + 5) * (v + 2)) / (v + 1)
   145  		}
   146  	}
   147  }
   148  
   149  func BenchmarkMediumBLoopIter_a_CSE_slow(b *testing.B) {
   150  	values := makeValues()
   151  	b.ReportAllocs()
   152  	// This runs somewhat slower because b.Loop will keep i alive.
   153  	//
   154  	// This relies on compiler common-subexpression-elimination to turn
   155  	// "values[i]" into a temporary that is NOT tracked by b.Loop.
   156  	for b.Loop() {
   157  		var sum int
   158  		// DO NOT MODERNIZE THIS LOOP.
   159  		for i := len(values) - 1; i >= 0; i-- {
   160  			sum += (values[i] * (values[i] + 1) * (values[i] + 2)) / (values[i] + 3)
   161  			sum += (values[i] * (values[i] + 4) * (values[i] + 3)) / (values[i] + 2)
   162  			sum += (values[i] * (values[i] + 5) * (values[i] + 2)) / (values[i] + 1)
   163  		}
   164  	}
   165  }
   166  
   167  func BenchmarkMediumBLoopIter_b_CSE_slow(b *testing.B) {
   168  	values := makeValues()
   169  	b.ReportAllocs()
   170  	// This runs somewhat slower because b.Loop will keep i alive.
   171  	//
   172  	// This relies on compiler common-subexpression-elimination to turn
   173  	// "values[i]" into a temporary that is NOT tracked by b.Loop.
   174  	var sum int
   175  	for b.Loop() {
   176  		// DO NOT MODERNIZE THIS LOOP.
   177  		for i := len(values) - 1; i >= 0; i-- {
   178  			sum += (values[i] * (values[i] + 1) * (values[i] + 2)) / (values[i] + 3)
   179  			sum += (values[i] * (values[i] + 4) * (values[i] + 3)) / (values[i] + 2)
   180  			sum += (values[i] * (values[i] + 5) * (values[i] + 2)) / (values[i] + 1)
   181  		}
   182  	}
   183  }
   184  
   185  func BenchmarkMediumBLoopIter_slow(b *testing.B) {
   186  	values := makeValues()
   187  	b.ReportAllocs()
   188  	// This runs slower because b.Loop will also keep i and v alive.
   189  	for b.Loop() {
   190  		var sum int
   191  		// DO NOT MODERNIZE THIS LOOP.
   192  		for i := len(values) - 1; i >= 0; i-- {
   193  			v := values[i]
   194  			sum += (v * (v + 1) * (v + 2)) / (v + 3)
   195  			sum += (v * (v + 4) * (v + 3)) / (v + 2)
   196  			sum += (v * (v + 5) * (v + 2)) / (v + 1)
   197  		}
   198  	}
   199  }
   200  
   201  func BenchmarkMediumBLoopIterSink_slow(b *testing.B) {
   202  	values := makeValues()
   203  	b.ReportAllocs()
   204  	var sum int
   205  	// This runs slower because b.Loop will also keep i and v alive.
   206  	for b.Loop() {
   207  		// DO NOT MODERNIZE THIS LOOP.
   208  		for i := len(values) - 1; i >= 0; i-- {
   209  			v := values[i]
   210  			sum += (v * (v + 1) * (v + 2)) / (v + 3)
   211  			sum += (v * (v + 4) * (v + 3)) / (v + 2)
   212  			sum += (v * (v + 5) * (v + 2)) / (v + 1)
   213  		}
   214  	}
   215  	gsum = sum
   216  }
   217  

View as plain text