Alexey Palazhchenko
April 14, 2017
180

# Профилирование и оптимизация программ на Go

Доклад на конференции Стачка 2017

April 14, 2017

## Transcript

2017, Стачка

2017, Стачка
3. None
4. None
5. None
6. None
7. None
8. None
9. ### type Cache interface { Get(id string) interface{} Set(id string, value

interface{}) Len() int }
10. ### func (s *Slice) Get(id string) interface{} { for _, it

:= range s.items { if it.id == id { return it.value } } return nil }
11. ### func (s *Slice) Set(id string, value i{}) { for i,

it := range s.items { if it.id == id { s.items[i].value = value return } } s.items = append(s.items, item{id, value}) }
12. ### func (s *Slice) Set(id string, value i{}) { for i,

it := range s.items { if it.id == id { s.items[i].value = value return } } s.items = append(s.items, item{id, value}) }
13. ### b.ResetTimer() for i := 0; i < b.N; i++ {

for _, id := range ids { Sink = c.Get(id) } }
14. ### 100 200 300 400 0 1 2 3 4 5

6 7 8 9 10 Slice Map
15. ### 100 200 300 400 0 1 2 3 4 5

6 7 8 9 10 Slice Map Fancy algorithms are slow when n is small, and n is usually small. - Rob Pike
16. ### Sink func popcnt(x uint64) int { var res uint64 for

; x > 0; x >>= 1 { res += x & 1 } return int(res) }
17. ### Sink const m1 = 0x5555555555555555 const m2 = 0x3333333333333333 const

m4 = 0x0f0f0f0f0f0f0f0f const h01 = 0x0101010101010101 func popcnt2(x uint64) int { x -= (x >> 1) & m1 x = (x & m2) + ((x >> 2) & m2) x = (x + (x >> 4)) & m4 return int((x * h01) >> 56) }
18. ### Sink func BenchmarkPopcnt(b *testing.B) { for i := 0; i

< b.N; i++ { popcnt(uint64(i)) } } func BenchmarkPopcnt2(b *testing.B) { for i := 0; i < b.N; i++ { popcnt2(uint64(i)) } }
19. ### Sink go test -v -bench=. BenchmarkPopcnt-4 100000000 15.5 ns/op BenchmarkPopcnt2-4

2000000000 0.34 ns/op
20. ### Sink go test -v -bench=. BenchmarkPopcnt-4 100000000 15.5 ns/op BenchmarkPopcnt2-4

2000000000 0.34 ns/op

"-S"
22. ### Sink popcnt_test.go:14 MOVQ "".b+8(FP), AX popcnt_test.go:14 MOVQ \$0, CX popcnt_test.go:14

MOVQ 200(AX), DX popcnt_test.go:14 CMPQ CX, DX popcnt_test.go:14 JGE \$0, 34 popcnt_test.go:14 INCQ CX popcnt_test.go:14 MOVQ 200(AX), DX popcnt_test.go:14 CMPQ CX, DX popcnt_test.go:14 JLT \$0, 19 popcnt_test.go:17 RET
23. ### Sink func BenchmarkPopcnt(b *testing.B) { for i := 0; i

< b.N; i++ { Sink = popcnt(uint64(i)) } } func BenchmarkPopcnt2(b *testing.B) { for i := 0; i < b.N; i++ { Sink = popcnt2(uint64(i)) } }
24. ### Sink go test -v -bench=. BenchmarkPopcnt-4 50000000 39.3 ns/op BenchmarkPopcnt2-4

50000000 26.8 ns/op

26. ### Benchmarks • Не в виртуальной машине • Не трогать во

время работы • Выключить автоматическое управление питанием • rsc.io/benchstat
27. ### pprof • runtime/pprof • net/http/pprof • go test • Не

больше одного за раз!
28. ### pprof: CPU • setitimer(2), ITIMER_PROF, SIGPROF • До 500 Гц

(100 по умолчанию) • SetCPUProﬁleRate(hz) • go test -bench=XXX -cpuproﬁle=XXX.pprof • go tool pprof -svg -output=XXX.svg cache.test XXX.pprof
29. None
30. None

32. ### type Map struct { m sync.Mutex items map[string]interface{} } func

(m *Map) Get(id string) interface{} { m.m.Lock() defer m.m.Unlock() return m.items[id] }
33. ### pprof: block • go test -v -bench=XXX -blockproﬁle=XXX.pprof • go

tool pprof -svg -lines -output=XXX.svg ccache.test XXX.pprof
34. None
35. ### type Map struct { m sync.RWMutex items map[string]interface{} } func

(m *Map) Get(id string) interface{} { m.m.RLock() v := m.items[id] m.m.RUnlock() return v }
36. ### pprof: свои профили • Когда нужны stack traces • Интеграция

с go tool pprof • Пример: открытие и закрытие файлов • pprof.NewProﬁle, pprof.Lookup • Proﬁle.Add, Remove
37. ### Execution tracer • Запуск, остановка, переключение горутин • Блокировки на

каналах, select • Блокировки на mutex’ах • Блокировки на сети, syscall’ах
38. ### Execution tracer • Все события с полным контекстом • Большие

файлы (со всеми символами) • Замедление ~25% • pprof CPU для throughput, tracer для latency
39. ### Execution tracer • import _ "net/http/pprof" • http://127.0.0.1:8080/debug/pprof • redis-benchmark

-r 100000 -e -l -t set,get • go tool trace trace.out
40. ### Execution tracer • go tool trace -pprof=TYPE trace.out > TYPE.pprof

• net • sync • syscall • sched

42. ### Переменные окружения • GOGC (100, off) • GODEBUG • gctrace=1

• allocfreetrace=1 • schedtrace=1000
43. ### Оптимизации • struct{} • m[string(b)] • for i, c :=

range []byte(s) • for i := range s { a[i] = <zero value> }
44. ### Оптимизации type Key [64]byte type Value struct { Name [32]byte

Balance uint64 Timestamp int64 } m := make(map[Key]Value, 1e8)
45. ### • golang-ru @ Google Groups • 4gophers.ru/slack • golangshow.com •

github.com/AlekSi/ stachka-2017