Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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

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

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

Alexey Palazhchenko

April 14, 2017
Tweet

More Decks by Alexey Palazhchenko

Other Decks in Programming

Transcript

  1. func (s *Slice) Get(id string) interface{} { for _, it

    := range s.items { if it.id == id { return it.value } } return nil }
  2. 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}) }
  3. 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}) }
  4. b.ResetTimer() for i := 0; i < b.N; i++ {

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

    6 7 8 9 10 Slice Map
  6. 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
  7. Sink func popcnt(x uint64) int { var res uint64 for

    ; x > 0; x >>= 1 { res += x & 1 } return int(res) }
  8. 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) }
  9. 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)) } }
  10. 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
  11. 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)) } }
  12. Benchmarks • Не в виртуальной машине • Не трогать во

    время работы • Выключить автоматическое управление питанием • rsc.io/benchstat
  13. pprof: CPU • setitimer(2), ITIMER_PROF, SIGPROF • До 500 Гц

    (100 по умолчанию) • SetCPUProfileRate(hz) • go test -bench=XXX -cpuprofile=XXX.pprof • go tool pprof -svg -output=XXX.svg cache.test XXX.pprof
  14. 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] }
  15. pprof: block • go test -v -bench=XXX -blockprofile=XXX.pprof • go

    tool pprof -svg -lines -output=XXX.svg ccache.test XXX.pprof
  16. 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 }
  17. pprof: свои профили • Когда нужны stack traces • Интеграция

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

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

    файлы (со всеми символами) • Замедление ~25% • pprof CPU для throughput, tracer для latency
  20. Оптимизации • struct{} • m[string(b)] • for i, c :=

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

    Balance uint64 Timestamp int64 } m := make(map[Key]Value, 1e8)