/libgo/go/runtime/pprof/mprof_test.go

https://gitlab.com/lobl.pavel/gcc-6.2.0 · Go · 99 lines · 70 code · 19 blank · 10 comment · 8 complexity · f3db7c3acbf17f686ff6e2613833f384 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 x]+
  61. # 0x[0-9,a-f]+ pprof_test\.allocatePersistent1K\+0x[0-9,a-f]+ .*/mprof_test\.go:40
  62. # 0x[0-9,a-f]+ runtime_pprof_test\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/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 x]+
  65. # 0x[0-9,a-f]+ pprof_test\.allocateTransient1M\+0x[0-9,a-f]+ .*/mprof_test.go:21
  66. # 0x[0-9,a-f]+ runtime_pprof_test\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/mprof_test.go:61
  67. `, (1<<10)*memoryProfilerRun, (1<<20)*memoryProfilerRun),
  68. // This should start with "0: 0" but gccgo's imprecise
  69. // GC means that sometimes the value is not collected.
  70. fmt.Sprintf(`(0|%v): (0|%v) \[%v: %v\] @ 0x[0-9,a-f x]+
  71. # 0x[0-9,a-f]+ pprof_test\.allocateTransient2M\+0x[0-9,a-f]+ .*/mprof_test.go:27
  72. # 0x[0-9,a-f]+ runtime_pprof_test\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/mprof_test.go:62
  73. `, memoryProfilerRun, (2<<20)*memoryProfilerRun, memoryProfilerRun, (2<<20)*memoryProfilerRun),
  74. }
  75. for _, test := range tests {
  76. if !regexp.MustCompile(test).Match(buf.Bytes()) {
  77. t.Fatalf("The entry did not match:\n%v\n\nProfile:\n%v\n", test, buf.String())
  78. }
  79. }
  80. }