Skip to content

Instantly share code, notes, and snippets.

@bwplotka
Last active February 20, 2020 11:53
Show Gist options
  • Save bwplotka/9e68b5be3e76b253166dbeea222efac7 to your computer and use it in GitHub Desktop.
Save bwplotka/9e68b5be3e76b253166dbeea222efac7 to your computer and use it in GitHub Desktop.
Showcase of Go "1.14beta1" vs "1.13.1" `defer` performance improvement.
package main
import (
"testing"
)
var sink1 = 0
func BenchmarkNotDefered(b *testing.B) {
for n := 0; n < b.N; n++ {
notDefered()
}
b.Log(sink1)
}
func notDefered() {
func() {
sink1++
}()
}
var sink2 = 0
func BenchmarkDefered(b *testing.B) {
for n := 0; n < b.N; n++ {
defered()
}
b.Log(sink2)
}
func defered() {
defer func() {
sink2++
}()
}
# Hardware:
#
# Model: Lenovo ThinkPad X1 Extreme 2nd
# CPU: 12x Intel(R) Core(TM) i7-9850H CPU @ 2.60GHz
# RAM memory: 32GB Intel Corporation Cannon Lake PCH Shared SRAM (rev 10)
# Linux pop-os 5.3.0-20-generic #21+system76~1572304854~19.10~8caa3e6-Ubuntu SMP Tue Oct 29 00:4 x86_64 x86_64 x86_64 GNU/Linux
# 1.13
go test -bench="Benchmark.*" -run=^$ -timeout 10m -benchtime 30s ./_dev/bench_defer/ | tee defer_1.13.out
goos: linux
goarch: amd64
pkg: github.com/thanos-io/thanos/_dev/bench_defer
BenchmarkNotDefered-12 1000000000 1.32 ns/op
--- BENCH: BenchmarkNotDefered-12
main_test.go:60: 1
main_test.go:60: 101
main_test.go:60: 10101
main_test.go:60: 1010101
main_test.go:60: 101010101
main_test.go:60: 1101010101
BenchmarkDefered-12 1000000000 31.1 ns/op
--- BENCH: BenchmarkDefered-12
main_test.go:75: 1
main_test.go:75: 101
main_test.go:75: 10101
main_test.go:75: 1010101
main_test.go:75: 101010101
main_test.go:75: 1101010101
PASS
ok github.com/thanos-io/thanos/_dev/bench_defer 35.679s
## 1.14beta1
go test -bench="Benchmark.*" -run=^$ -timeout 10m -benchtime 30s ./_dev/bench_defer/ | tee defer_1.14.out
goos: linux
goarch: amd64
pkg: github.com/thanos-io/thanos/_dev/bench_defer
BenchmarkNotDefered-12 1000000000 1.32 ns/op
--- BENCH: BenchmarkNotDefered-12
main_test.go:60: 1
main_test.go:60: 101
main_test.go:60: 10101
main_test.go:60: 1010101
main_test.go:60: 101010101
main_test.go:60: 1101010101
BenchmarkDefered-12 1000000000 2.76 ns/op
--- BENCH: BenchmarkDefered-12
main_test.go:75: 1
main_test.go:75: 101
main_test.go:75: 10101
main_test.go:75: 1010101
main_test.go:75: 101010101
main_test.go:75: 1101010101
PASS
ok github.com/thanos-io/thanos/_dev/bench_defer 4.690s
# cmp
benchcmp defer_1.13.out defer_1.14.out
benchmark old ns/op new ns/op delta
BenchmarkNotDefered-12 1.32 1.32 +0.00%
BenchmarkDefered-12 31.1 2.76 -91.13%
package main
import "sync"
var mtx sync.Mutex
func performanceCriticalMethod() {
mtx.Lock()
defer mtx.Unlock()
// ...do something FAST!
}
// Excerpt from: https://github.com/golang/go/blob/go1.11.4/src/crypto/tls/conn.go#L1036
package tls
// ...
import "sync/atomic"
// Write writes data to the connection.
func (c *Conn) Write(b []byte) (int, error) {
// interlock with Close below
for {
x := atomic.LoadInt32(&c.activeCall)
if x&1 != 0 {
return 0, errClosed
}
if atomic.CompareAndSwapInt32(&c.activeCall, x, x+2) {
defer atomic.AddInt32(&c.activeCall, -2)
break
}
}
// Rest...
}
package main
import (
"net/http"
"time"
"github.com/prometheus/client_golang/prometheus"
)
type handler struct {
latency prometheus.Histogram
}
// Performance critical HTTP handler.
func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
start := time.Now()
defer func() {
// Probably this is not great example, as this `Observe` methods is much slower that defer improvement.
h.latency.Observe(time.Since(start).Seconds())
}()
// Handling...
w.WriteHeader(http.StatusOK)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment