/src/runtime/pprof/mprof_test.go

https://gitlab.com/OBSERVER-DLL/go · Go · 96 lines · 70 code · 18 blank · 8 comment · 8 complexity · 4ee51735cd603025e63d72d81e9edc14 MD5 · raw file

  1. // Copyright 2014 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package pprof_test
  5. import (
  6. "bytes"
  7. "fmt"
  8. "regexp"
  9. "runtime"
  10. . "runtime/pprof"
  11. "testing"
  12. "unsafe"
  13. )
  14. var memSink interface{}
  15. func allocateTransient1M() {
  16. for i := 0; i < 1024; i++ {
  17. memSink = &struct{ x [1024]byte }{}
  18. }
  19. }
  20. //go:noinline
  21. func allocateTransient2M() {
  22. memSink = make([]byte, 2<<20)
  23. }
  24. type Obj32 struct {
  25. link *Obj32
  26. pad [32 - unsafe.Sizeof(uintptr(0))]byte
  27. }
  28. var persistentMemSink *Obj32
  29. func allocatePersistent1K() {
  30. for i := 0; i < 32; i++ {
  31. // Can't use slice because that will introduce implicit allocations.
  32. obj := &Obj32{link: persistentMemSink}
  33. persistentMemSink = obj
  34. }
  35. }
  36. var memoryProfilerRun = 0
  37. func TestMemoryProfiler(t *testing.T) {
  38. // Disable sampling, otherwise it's difficult to assert anything.
  39. oldRate := runtime.MemProfileRate
  40. runtime.MemProfileRate = 1
  41. defer func() {
  42. runtime.MemProfileRate = oldRate
  43. }()
  44. // Allocate a meg to ensure that mcache.next_sample is updated to 1.
  45. for i := 0; i < 1024; i++ {
  46. memSink = make([]byte, 1024)
  47. }
  48. // Do the interesting allocations.
  49. allocateTransient1M()
  50. allocateTransient2M()
  51. allocatePersistent1K()
  52. memSink = nil
  53. runtime.GC() // materialize stats
  54. var buf bytes.Buffer
  55. if err := Lookup("heap").WriteTo(&buf, 1); err != nil {
  56. t.Fatalf("failed to write heap profile: %v", err)
  57. }
  58. memoryProfilerRun++
  59. tests := []string{
  60. fmt.Sprintf(`%v: %v \[%v: %v\] @ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+
  61. # 0x[0-9,a-f]+ runtime/pprof_test\.allocatePersistent1K\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test\.go:40
  62. # 0x[0-9,a-f]+ runtime/pprof_test\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test\.go:63
  63. `, 32*memoryProfilerRun, 1024*memoryProfilerRun, 32*memoryProfilerRun, 1024*memoryProfilerRun),
  64. fmt.Sprintf(`0: 0 \[%v: %v\] @ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+
  65. # 0x[0-9,a-f]+ runtime/pprof_test\.allocateTransient1M\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:21
  66. # 0x[0-9,a-f]+ runtime/pprof_test\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:61
  67. `, (1<<10)*memoryProfilerRun, (1<<20)*memoryProfilerRun),
  68. fmt.Sprintf(`0: 0 \[%v: %v\] @ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+
  69. # 0x[0-9,a-f]+ runtime/pprof_test\.allocateTransient2M\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:27
  70. # 0x[0-9,a-f]+ runtime/pprof_test\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:62
  71. `, memoryProfilerRun, (2<<20)*memoryProfilerRun),
  72. }
  73. for _, test := range tests {
  74. if !regexp.MustCompile(test).Match(buf.Bytes()) {
  75. t.Fatalf("The entry did not match:\n%v\n\nProfile:\n%v\n", test, buf.String())
  76. }
  77. }
  78. }