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