github.com/miolini/go@v0.0.0-20160405192216-fca68c8cb408/src/runtime/pprof/mprof_test.go (about)

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