Measure performance changes with benchcmp

📅 Tue, Jan 26, 2016 ⏱️ 2-minute read

go test -bench=.

Go has a great option to write your benchmarks and run it together with go test with option -bench. To create a benchmark function you must do the following:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
package anonymizer

import "testing"

func BenchmarkAnonymizerShortString(b *testing.B) {
	for n := 0; n < b.N; n++ {
		Anonymizer("This is a secret message with my private email john@gmail.com")
	}
}

func BenchmarkAnonymizerLongString(b *testing.B) {
	for n := 0; n < b.N; n++ {
		Anonymizer("This is a secret message with my private emails: john@gmail.com, john@gmail.com, john@gmail.com, john@gmail.com, john@gmail.com, john@gmail.com, john@gmail.com.")
	}
}

Anonymizer() function searchs for emails in the string and replaces it to “****”.

1
2
3
4
5
6
go test -bench=. > old.txt && cat old.txt

PASS
BenchmarkAnonymizerShortString	   30000	     49060 ns/op
BenchmarkAnonymizerLongString 	   20000	     67854 ns/op
ok  	anonymizer	4.042s

Improve Anonymizer()

Let me show you this Anonymizer():

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package anonymizer

import (
	"regexp"
	"strings"
)

// Anonymizer func
func Anonymizer(s string) string {
	re, err := regexp.Compile("[A-Za-z0-9](([_\\.\\-]?[a-zA-Z0-9]+)*)@([A-Za-z0-9]+)(([\\.\\-]?[a-zA-Z0-9]+)*)\\.([A-Za-z]{2,})")
	if err != nil {
		return s
	}

	matches := re.FindAllString(s, -1)
	for _, matchStr := range matches {
		matchStr = strings.Trim(matchStr, " ")
		if matchStr != "" {
			s = strings.Replace(s, matchStr, "****", -1)
		}
	}

	return s
}

Then I decided that this RegExp is a bit complicated and replaced it to the one sufficient for all practical purposes:

1
re, err := regexp.Compile("(\\w[-._\\w]*\\w@\\w[-._\\w]*\\w\\.\\w{2,3})")

And run go test again:

1
go test -bench=. > new.txt

Measure our improvement

So now we have 2 versions of our code and benchmark results for both, lets use benchcmp tool to measure a growth of performance:

1
2
3
4
5
6
go get golang.org/x/tools/cmd/benchcmp

benchcmp old.txt new.txt
benchmark                          old ns/op     new ns/op     delta
BenchmarkAnonymizerShortString     50225         40648         -19.07%
BenchmarkAnonymizerLongString      69017         54494         -21.04%

Negative values are good, it means that 1 operation calculates faster after our changes. Of cause this benchmark is artificial and values can be different even on the same environment, so don’t forget it and repeat your experiments.

Feedback

As always, please reach out to me on X with questions, corrections, or ideas!