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

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

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

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

Avatar for Alexey Palazhchenko

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)