// Copyright 2026 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 rangefunc_test import ( "slices" "testing" ) // These benchmarks, Tiny and Medium, do NOT all run in the same amount // of time. var gsum int func makeValues() []int { values := make([]int, 64) for i := range values { values[i] = i + 1 } return values } func BenchmarkTinyIterIter(b *testing.B) { values := makeValues() b.ReportAllocs() // DO NOT MODERNIZE THIS LOOP. for k := 0; k < b.N; k++ { // DO NOT MODERNIZE THIS LOOP. var sum int = 1 for i := len(values) - 1; i >= 0; i-- { sum *= values[i] } } } func BenchmarkTinyIterIterSink(b *testing.B) { values := makeValues() b.ReportAllocs() var sum int = 1 // DO NOT MODERNIZE THIS LOOP. for k := 0; k < b.N; k++ { // DO NOT MODERNIZE THIS LOOP. for i := len(values) - 1; i >= 0; i-- { sum *= values[i] } } gsum = sum } // BenchmarkTinyIterRangeSink should run as quickly as BenchmarkTinyIterIterSink. func BenchmarkTinyIterRangeSink(b *testing.B) { values := makeValues() b.ReportAllocs() var sum int = 1 // DO NOT MODERNIZE THIS LOOP. for k := 0; k < b.N; k++ { for _, v := range slices.Backward(values) { sum *= v } } gsum = sum } func BenchmarkTinyBloopIter(b *testing.B) { values := makeValues() b.ReportAllocs() for b.Loop() { var sum int = 1 // DO NOT MODERNIZE THIS LOOP. for i := len(values) - 1; i >= 0; i-- { sum *= values[i] } } } // BenchmarkTinyBloopRange should run as quickly as BenchmarkTinyBloopIter. func BenchmarkTinyBloopRange(b *testing.B) { values := makeValues() b.ReportAllocs() for b.Loop() { var sum int = 1 for _, v := range slices.Backward(values) { sum *= v } } } func BenchmarkMediumIterIterSink(b *testing.B) { values := makeValues() b.ReportAllocs() var sum int // DO NOT MODERNIZE THIS LOOP. for k := 0; k < b.N; k++ { // DO NOT MODERNIZE THIS LOOP. for i := len(values) - 1; i >= 0; i-- { v := values[i] sum += (v * (v + 1) * (v + 2)) / (v + 3) sum += (v * (v + 4) * (v + 3)) / (v + 2) sum += (v * (v + 5) * (v + 2)) / (v + 1) } } gsum = sum } func BenchmarkMediumIterRangeSink(b *testing.B) { values := makeValues() b.ReportAllocs() var sum int // DO NOT MODERNIZE THIS LOOP. for k := 0; k < b.N; k++ { for _, v := range slices.Backward(values) { sum += (v * (v + 1) * (v + 2)) / (v + 3) sum += (v * (v + 4) * (v + 3)) / (v + 2) sum += (v * (v + 5) * (v + 2)) / (v + 1) } } gsum = sum } func BenchmarkMediumBLoopIterSink(b *testing.B) { values := makeValues() b.ReportAllocs() var sum int for b.Loop() { for _, v := range slices.Backward(values) { sum += (v * (v + 1) * (v + 2)) / (v + 3) sum += (v * (v + 4) * (v + 3)) / (v + 2) sum += (v * (v + 5) * (v + 2)) / (v + 1) } } gsum = sum } func BenchmarkMediumBLoopIter(b *testing.B) { values := makeValues() b.ReportAllocs() for b.Loop() { var sum int for _, v := range slices.Backward(values) { sum += (v * (v + 1) * (v + 2)) / (v + 3) sum += (v * (v + 4) * (v + 3)) / (v + 2) sum += (v * (v + 5) * (v + 2)) / (v + 1) } } } func BenchmarkMediumBLoopIter_a_CSE_slow(b *testing.B) { values := makeValues() b.ReportAllocs() // This runs somewhat slower because b.Loop will keep i alive. // // This relies on compiler common-subexpression-elimination to turn // "values[i]" into a temporary that is NOT tracked by b.Loop. for b.Loop() { var sum int // DO NOT MODERNIZE THIS LOOP. for i := len(values) - 1; i >= 0; i-- { sum += (values[i] * (values[i] + 1) * (values[i] + 2)) / (values[i] + 3) sum += (values[i] * (values[i] + 4) * (values[i] + 3)) / (values[i] + 2) sum += (values[i] * (values[i] + 5) * (values[i] + 2)) / (values[i] + 1) } } } func BenchmarkMediumBLoopIter_b_CSE_slow(b *testing.B) { values := makeValues() b.ReportAllocs() // This runs somewhat slower because b.Loop will keep i alive. // // This relies on compiler common-subexpression-elimination to turn // "values[i]" into a temporary that is NOT tracked by b.Loop. var sum int for b.Loop() { // DO NOT MODERNIZE THIS LOOP. for i := len(values) - 1; i >= 0; i-- { sum += (values[i] * (values[i] + 1) * (values[i] + 2)) / (values[i] + 3) sum += (values[i] * (values[i] + 4) * (values[i] + 3)) / (values[i] + 2) sum += (values[i] * (values[i] + 5) * (values[i] + 2)) / (values[i] + 1) } } } func BenchmarkMediumBLoopIter_slow(b *testing.B) { values := makeValues() b.ReportAllocs() // This runs slower because b.Loop will also keep i and v alive. for b.Loop() { var sum int // DO NOT MODERNIZE THIS LOOP. for i := len(values) - 1; i >= 0; i-- { v := values[i] sum += (v * (v + 1) * (v + 2)) / (v + 3) sum += (v * (v + 4) * (v + 3)) / (v + 2) sum += (v * (v + 5) * (v + 2)) / (v + 1) } } } func BenchmarkMediumBLoopIterSink_slow(b *testing.B) { values := makeValues() b.ReportAllocs() var sum int // This runs slower because b.Loop will also keep i and v alive. for b.Loop() { // DO NOT MODERNIZE THIS LOOP. for i := len(values) - 1; i >= 0; i-- { v := values[i] sum += (v * (v + 1) * (v + 2)) / (v + 3) sum += (v * (v + 4) * (v + 3)) / (v + 2) sum += (v * (v + 5) * (v + 2)) / (v + 1) } } gsum = sum }