| // Copyright 2021 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 test |
| |
| import ( |
| "math/bits" |
| "testing" |
| ) |
| |
| func BenchmarkSwitch8Predictable(b *testing.B) { |
| benchmarkSwitch8(b, true) |
| } |
| func BenchmarkSwitch8Unpredictable(b *testing.B) { |
| benchmarkSwitch8(b, false) |
| } |
| func benchmarkSwitch8(b *testing.B, predictable bool) { |
| n := 0 |
| rng := newRNG() |
| for i := 0; i < b.N; i++ { |
| rng = rng.next(predictable) |
| switch rng.value() & 7 { |
| case 0: |
| n += 1 |
| case 1: |
| n += 2 |
| case 2: |
| n += 3 |
| case 3: |
| n += 4 |
| case 4: |
| n += 5 |
| case 5: |
| n += 6 |
| case 6: |
| n += 7 |
| case 7: |
| n += 8 |
| } |
| } |
| sink = n |
| } |
| |
| func BenchmarkSwitch32Predictable(b *testing.B) { |
| benchmarkSwitch32(b, true) |
| } |
| func BenchmarkSwitch32Unpredictable(b *testing.B) { |
| benchmarkSwitch32(b, false) |
| } |
| func benchmarkSwitch32(b *testing.B, predictable bool) { |
| n := 0 |
| rng := newRNG() |
| for i := 0; i < b.N; i++ { |
| rng = rng.next(predictable) |
| switch rng.value() & 31 { |
| case 0, 1, 2: |
| n += 1 |
| case 4, 5, 6: |
| n += 2 |
| case 8, 9, 10: |
| n += 3 |
| case 12, 13, 14: |
| n += 4 |
| case 16, 17, 18: |
| n += 5 |
| case 20, 21, 22: |
| n += 6 |
| case 24, 25, 26: |
| n += 7 |
| case 28, 29, 30: |
| n += 8 |
| default: |
| n += 9 |
| } |
| } |
| sink = n |
| } |
| |
| func BenchmarkSwitchStringPredictable(b *testing.B) { |
| benchmarkSwitchString(b, true) |
| } |
| func BenchmarkSwitchStringUnpredictable(b *testing.B) { |
| benchmarkSwitchString(b, false) |
| } |
| func benchmarkSwitchString(b *testing.B, predictable bool) { |
| a := []string{ |
| "foo", |
| "foo1", |
| "foo22", |
| "foo333", |
| "foo4444", |
| "foo55555", |
| "foo666666", |
| "foo7777777", |
| } |
| n := 0 |
| rng := newRNG() |
| for i := 0; i < b.N; i++ { |
| rng = rng.next(predictable) |
| switch a[rng.value()&7] { |
| case "foo": |
| n += 1 |
| case "foo1": |
| n += 2 |
| case "foo22": |
| n += 3 |
| case "foo333": |
| n += 4 |
| case "foo4444": |
| n += 5 |
| case "foo55555": |
| n += 6 |
| case "foo666666": |
| n += 7 |
| case "foo7777777": |
| n += 8 |
| } |
| } |
| sink = n |
| } |
| |
| // A simple random number generator used to make switches conditionally predictable. |
| type rng uint64 |
| |
| func newRNG() rng { |
| return 1 |
| } |
| func (r rng) next(predictable bool) rng { |
| if predictable { |
| return r + 1 |
| } |
| return rng(bits.RotateLeft64(uint64(r), 13) * 0x3c374d) |
| } |
| func (r rng) value() uint64 { |
| return uint64(r) |
| } |