Save 37% off PRO during our Black Friday Sale! »

go-perftuner

 go-perftuner

64a4ba69d50590e592cd8e572454daa8?s=128

Oleg Kovalov

April 25, 2019
Tweet

Transcript

  1. go-perftuner WARSAW, APR 25 2019 Oleg Kovalov Allegro Twitter: oleg_kovalov

    Github: cristaloleg
  2. Me

  3. What is a performance optimization?

  4. What is a performance optimization?

  5. What is a performance optimization?

  6. What is a performance optimization?

  7. What is a performance optimization?

  8. What is a performance optimization?

  9. When performance optimization is needed?

  10. When performance optimization is needed?

  11. When performance optimization is needed?

  12. When performance optimization is needed?

  13. When performance optimization is needed?

  14. When performance optimization is needed?

  15. When performance optimization is needed?

  16. When performance optimization is needed?

  17. When performance optimization isn’t needed?

  18. When performance optimization isn’t needed?

  19. When performance optimization isn’t needed?

  20. When performance optimization isn’t needed?

  21. When performance optimization isn’t needed?

  22. When performance optimization isn’t needed?

  23. When performance optimization isn’t needed?

  24. Types of performance tuning

  25. Types of performance tuning

  26. Types of performance tuning

  27. Types of performance tuning

  28. Types of performance tuning

  29. Types of performance tuning

  30. Types of performance tuning

  31. Types of performance tuning

  32. Types of performance tuning

  33. What Go compiler can do?

  34. What Go compiler can do?

  35. What Go compiler can do?

  36. What Go compiler can do?

  37. So, welcome go-perftuner

  38. So, welcome go-perftuner

  39. So, welcome go-perftuner

  40. So, welcome go-perftuner

  41. So, welcome go-perftuner

  42. So, welcome go-perftuner

  43. Code inlining

  44. Code inlining

  45. Code inlining

  46. Code inlining

  47. Code inlining

  48. func ReadRuneSimple(s string) (ch rune, size int) { if len(s)

    == 0 { return } ch, size = utf8.DecodeRuneInString(s) return } almostInlined example (1)
  49. func ReadRuneSimple(s string) (ch rune, size int) { if len(s)

    == 0 { return } ch, size = utf8.DecodeRuneInString(s) return } $ go-perftuner inl -threshold=100 old.go almostInlined example (1)
  50. func ReadRuneSimple(s string) (ch rune, size int) { if len(s)

    == 0 { return } ch, size = utf8.DecodeRuneInString(s) return } $ go-perftuner inl -threshold=100 old.go $ almostInlined example (1)
  51. func ReadRuneLogged(s string) (ch rune, size int) { if len(s)

    == 0 { return } log.Printf("we're working") ch, size = utf8.DecodeRuneInString(s) return } $ go-perftuner inl -threshold=100 new.go almostInlined example (2)
  52. func ReadRuneLogged(s string) (ch rune, size int) { if len(s)

    == 0 { return } log.Printf("we're working") ch, size = utf8.DecodeRuneInString(s) return } $ go-perftuner inl -threshold=100 new.go inl: ./new.go:34:6: ReadRuneLogged: budget exceeded by 50 almostInlined example (2)
  53. Bounds-checking elimination

  54. Bounds-checking elimination

  55. Bounds-checking elimination

  56. Bounds-checking elimination

  57. boundChecks example (1) func PutUint32(b []byte, v uint32) { b[0]

    = byte(v) b[1] = byte(v >> 8) b[2] = byte(v >> 16) b[3] = byte(v >> 24) }
  58. boundChecks example (2) func PutUint32(b []byte, v uint32) { b[0]

    = byte(v) b[1] = byte(v >> 8) b[2] = byte(v >> 16) b[3] = byte(v >> 24) } $ go-perftuner bce old.go bce: ./old.go:4:7: slice/array has bound checks bce: ./old.go:5:7: slice/array has bound checks bce: ./old.go:6:7: slice/array has bound checks bce: ./old.go:7:7: slice/array has bound checks $
  59. func PutUint32(b []byte, v uint32) { _ = b[3] //

    early check to guarantee safety b[0] = byte(v) b[1] = byte(v >> 8) b[2] = byte(v >> 16) b[3] = byte(v >> 24) } boundChecks example (3)
  60. boundChecks example (4) func PutUint32(b []byte, v uint32) { _

    = b[3] // early check to guarantee safety b[0] = byte(v) b[1] = byte(v >> 8) b[2] = byte(v >> 16) b[3] = byte(v >> 24) } $ go-perftuner bce new.go bce: ./new.go:4:7: slice/array has bound checks $
  61. boundChecks example (4) func PutUint32(b []byte, v uint32) { if

    len(b) < 4 { return } b[0] = byte(v) b[1] = byte(v >> 8) b[2] = byte(v >> 16) b[3] = byte(v >> 24) } $ go-perftuner bce new.go $
  62. Escape analysis

  63. Escape analysis

  64. Escape analysis

  65. Escape analysis

  66. func getRands(size int) []int { nums := make([]int, size) for

    i := range nums { nums[i] = rand.Int() } return nums } escapedVariable example (1)
  67. func getRands(size int) []int { nums := make([]int, size) for

    i := range nums { nums[i] = rand.Int() } return nums } $ go-perftuner esc old.go esc: ./old.go:16:14: make([]int, size) $ escapedVariable example (1)
  68. func sumRand() (total int) { nums := make([]int, 8191) for

    i := range nums { nums[i] = rand.Int() } for _, x := range nums { total += x } return total } escapedVariable example (2)
  69. func sumRand() (total int) { nums := make([]int, 8191) for

    i := range nums { nums[i] = rand.Int() } for _, x := range nums { total += x } return total } $ go-perftuner esc 1.go $ escapedVariable example (3)
  70. func sumRand() (total int) { nums := make([]int, 8191 +

    1) for i := range nums { nums[i] = rand.Int() } for _, x := range nums { total += x } return total } $ go-perftuner esc 1.go escapedVariable example (4)
  71. func sumRand() (total int) { nums := make([]int, 8191 +

    1) for i := range nums { nums[i] = rand.Int() } for _, x := range nums { total += x } return total } $ go-perftuner esc 1.go esc: ./old.go:16:14: make([]int, 8191 + 1) $ escapedVariable example (4)
  72. A very handy tool

  73. A very handy tool

  74. A very handy tool

  75. A very handy tool

  76. $ go get golang.org/x/perf/cmd/benchstat $ go test -bench=. -count 10

    > old.txt benchstat
  77. $ go get golang.org/x/perf/cmd/benchstat $ go test -bench=. -count 10

    > old.txt $ # < do some coding and magic with go-perftuner > $ go test -bench=. -count 10 > new.txt benchstat
  78. benchstat $ go get golang.org/x/perf/cmd/benchstat $ go test -bench=. -count

    10 > old.txt $ # < do some coding and magic with go-perftuner > $ go test -bench=. -count 10 > new.txt $ benchstat old.txt new.txt name old time/op new time/op delta Foo 13.6ms ± 1% 11.8ms ± 1% -13.31% (p=0.016 n=4+5) Bar 32.1ms ± 1% 31.8ms ± 1% ~ (p=0.286 n=4+5)
  79. Performance tuning summary

  80. Performance tuning summary

  81. Performance tuning summary

  82. Performance tuning summary

  83. Performance tuning summary

  84. Performance tuning summary

  85. That’s all folks