These steps cover writing and running your application:
- From your Terminal or console application, create a new directory called ~/projects/go-programming-cookbook/chapter14/bench and navigate to this directory.
- Run this command:
$ go mod init github.com/PacktPublishing/Go-Programming-Cookbook-Second-Edition/chapter14/bench
You should see a file called go.mod that contains the following:
module github.com/PacktPublishing/Go-Programming-Cookbook-Second-Edition/chapter14/bench
- Copy tests from ~/projects/go-programming-cookbook-original/chapter14/bench, or use this as an exercise to write some of your own code!
Note that copied tests also include benchmarks written later in this recipe.
- Create a file called lock.go with the following content:
package bench
import "sync"
// Counter uses a sync.RWMutex to safely
// modify a value
type Counter struct {
value int64
mu *sync.RWMutex
}
// Add increments the counter
func (c *Counter) Add(amount int64) {
c.mu.Lock()
c.value += amount
c.mu.Unlock()
}
// Read returns the current counter amount
func (c *Counter) Read() int64 {
c.mu.RLock()
defer c.mu.RUnlock()
return c.value
}
- Create a file called atomic.go with the following content:
package bench
import "sync/atomic"
// AtomicCounter implements an atmoic lock
// using the atomic package
type AtomicCounter struct {
value int64
}
// Add increments the counter
func (c *AtomicCounter) Add(amount int64) {
atomic.AddInt64(&c.value, amount)
}
// Read returns the current counter amount
func (c *AtomicCounter) Read() int64 {
var result int64
result = atomic.LoadInt64(&c.value)
return result
}
- Create a file called lock_test.go with the following content:
package bench
import "testing"
func BenchmarkCounterAdd(b *testing.B) {
c := Counter{0, &sync.RWMutex{}}
for n := 0; n < b.N; n++ {
c.Add(1)
}
}
func BenchmarkCounterRead(b *testing.B) {
c := Counter{0, &sync.RWMutex{}}
for n := 0; n < b.N; n++ {
c.Read()
}
}
func BenchmarkCounterAddRead(b *testing.B) {
c := Counter{0, &sync.RWMutex{}}
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
c.Add(1)
c.Read()
}
})
}
- Create a file called atomic_test.go with the following content:
package bench
import "testing"
func BenchmarkAtomicCounterAdd(b *testing.B) {
c := AtomicCounter{0}
for n := 0; n < b.N; n++ {
c.Add(1)
}
}
func BenchmarkAtomicCounterRead(b *testing.B) {
c := AtomicCounter{0}
for n := 0; n < b.N; n++ {
c.Read()
}
}
func BenchmarkAtomicCounterAddRead(b *testing.B) {
c := AtomicCounter{0}
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
c.Add(1)
c.Read()
}
})
}
- Run the go test -bench . command, and you will see the following output:
$ go test -bench .
BenchmarkAtomicCounterAdd-4 200000000 8.38 ns/op
BenchmarkAtomicCounterRead-4 1000000000 2.09 ns/op
BenchmarkAtomicCounterAddRead-4 50000000 24.5 ns/op
BenchmarkCounterAdd-4 50000000 34.8 ns/op
BenchmarkCounterRead-4 20000000 66.0 ns/op
BenchmarkCounterAddRead-4 10000000 146 ns/op
PASS
ok github.com/PacktPublishing/Go-Programming-Cookbook-Second-
Edition/chapter14/bench 10.919s
- If you have copied or written your own tests, go up one directory and run go test. Ensure that all the tests pass.