Skip to content

Commit bf6711d

Browse files
authored
feat: Update benchmarking to use b.Loop() and bump go specification to 1.24 (#862)
* feat: update go specifcation to 1.24 * feat: update benchmarking to use b.Loop()
1 parent 9980f13 commit bf6711d

File tree

10 files changed

+27
-21
lines changed

10 files changed

+27
-21
lines changed

.github/workflows/go.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
- name: Set up Go
1919
uses: actions/setup-go@v5
2020
with:
21-
go-version: 1.23
21+
go-version: 1.24
2222

2323
- name: Build
2424
run: ./build.sh

blogrenderer/renderer_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,7 @@ func BenchmarkRender(b *testing.B) {
6363
b.Fatal(err)
6464
}
6565

66-
b.ResetTimer()
67-
for i := 0; i < b.N; i++ {
66+
for b.Loop() {
6867
postRenderer.Render(io.Discard, aPost)
6968
}
7069
}

concurrency.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,8 @@ func BenchmarkCheckWebsites(b *testing.B) {
9292
for i := 0; i < len(urls); i++ {
9393
urls[i] = "a url"
9494
}
95-
b.ResetTimer()
96-
for i := 0; i < b.N; i++ {
95+
96+
for b.Loop() {
9797
CheckWebsites(slowStubWebsiteChecker, urls)
9898
}
9999
}
@@ -102,8 +102,7 @@ func BenchmarkCheckWebsites(b *testing.B) {
102102
The benchmark tests `CheckWebsites` using a slice of one hundred urls and uses
103103
a new fake implementation of `WebsiteChecker`. `slowStubWebsiteChecker` is
104104
deliberately slow. It uses `time.Sleep` to wait exactly twenty milliseconds and
105-
then it returns true. We use `b.ResetTimer()` in this test to reset the time of our
106-
test before it actually runs
105+
then it returns true.
107106

108107

109108
When we run the benchmark using `go test -bench=.` (or if you're in Windows Powershell `go test -bench="."`):

concurrency/v1/check_websites_benchmark_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ func BenchmarkCheckWebsites(b *testing.B) {
1616
urls[i] = "a url"
1717
}
1818

19-
for i := 0; i < b.N; i++ {
19+
for b.Loop() {
2020
CheckWebsites(slowStubWebsiteChecker, urls)
2121
}
2222
}

concurrency/v2/check_websites_benchmark_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ func BenchmarkCheckWebsites(b *testing.B) {
1616
urls[i] = "a url"
1717
}
1818

19-
for i := 0; i < b.N; i++ {
19+
for b.Loop() {
2020
CheckWebsites(slowStubWebsiteChecker, urls)
2121
}
2222
}

concurrency/v3/check_websites_benchmark_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ func BenchmarkCheckWebsites(b *testing.B) {
1616
urls[i] = "a url"
1717
}
1818

19-
for i := 0; i < b.N; i++ {
19+
for b.Loop() {
2020
CheckWebsites(slowStubWebsiteChecker, urls)
2121
}
2222
}

for/vx/repeat_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ func TestRepeat(t *testing.T) {
1212
}
1313

1414
func BenchmarkRepeat(b *testing.B) {
15-
for i := 0; i < b.N; i++ {
15+
for b.Loop() {
1616
Repeat("a")
1717
}
1818
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module github.com/quii/learn-go-with-tests
22

3-
go 1.23
3+
go 1.24
44

55
require (
66
github.com/approvals/go-approval-tests v0.0.0-20211008131110-0c40b30e0000

html-templates.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -557,8 +557,7 @@ func BenchmarkRender(b *testing.B) {
557557
}
558558
)
559559

560-
b.ResetTimer()
561-
for i := 0; i < b.N; i++ {
560+
for b.Loop() {
562561
blogrenderer.Render(io.Discard, aPost)
563562
}
564563
}
@@ -646,8 +645,7 @@ func BenchmarkRender(b *testing.B) {
646645
b.Fatal(err)
647646
}
648647

649-
b.ResetTimer()
650-
for i := 0; i < b.N; i++ {
648+
for b.Loop() {
651649
postRenderer.Render(io.Discard, aPost)
652650
}
653651
}

iteration.md

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -97,19 +97,19 @@ Writing [benchmarks](https://golang.org/pkg/testing/#hdr-Benchmarks) in Go is an
9797

9898
```go
9999
func BenchmarkRepeat(b *testing.B) {
100-
for i := 0; i < b.N; i++ {
100+
for b.Loop() {
101101
Repeat("a")
102102
}
103103
}
104104
```
105105

106106
You'll see the code is very similar to a test.
107107

108-
The `testing.B` gives you access to the cryptically named `b.N`.
108+
The `testing.B` gives you access to the loop function. `Loop()` returns true as long as the benchmark should continue running.
109109

110-
When the benchmark code is executed, it runs `b.N` times and measures how long it takes.
110+
When the benchmark code is executed, it measures how long it takes. After `Loop()` returns false, `b.N` contains the total number of iterations that ran.
111111

112-
The amount of times the code is run shouldn't matter to you, the framework will determine what is a "good" value for that to let you have some decent results.
112+
The number of times the code is run shouldn't matter to you, the framework will determine what is a "good" value for that to let you have some decent results.
113113

114114
To run the benchmarks do `go test -bench=.` (or if you're in Windows Powershell `go test -bench="."`)
115115

@@ -125,7 +125,17 @@ What `136 ns/op` means is our function takes on average 136 nanoseconds to run \
125125

126126
**Note:** By default benchmarks are run sequentially.
127127

128-
**Note:** Sometimes, Go can optimize your benchmarks in a way that makes them inaccurate, such as eliminating the function being benchmarked. Check your benchmarks to see if the values make sense. If they seem overly optimized, you can follow the strategies in this **[blog post](https://dave.cheney.net/2013/06/30/how-to-write-benchmarks-in-go)**.
128+
Only the body of the loop is timed; it automatically excludes setup and cleanup code from benchmark timing. A typical benchmark is structured like:
129+
130+
```go
131+
func Benchmark(b *testing.B) {
132+
//... setup ...
133+
for b.Loop() {
134+
//... code to measure ...
135+
}
136+
//... cleanup ...
137+
}
138+
```
129139

130140
Strings in Go are immutable, meaning every concatenation, such as in our `Repeat` function, involves copying memory to accommodate the new string. This impacts performance, particularly during heavy string concatenation.
131141

0 commit comments

Comments
 (0)