github.com/slayercat/go@v0.0.0-20170428012452-c51559813f61/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
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"reflect"
    11  	"regexp"
    12  	"runtime"
    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  // Allocate transient memory using reflect.Call.
    46  
    47  func allocateReflectTransient() {
    48  	memSink = make([]byte, 2<<20)
    49  }
    50  
    51  func allocateReflect() {
    52  	rv := reflect.ValueOf(allocateReflectTransient)
    53  	rv.Call(nil)
    54  }
    55  
    56  var memoryProfilerRun = 0
    57  
    58  func TestMemoryProfiler(t *testing.T) {
    59  	// Disable sampling, otherwise it's difficult to assert anything.
    60  	oldRate := runtime.MemProfileRate
    61  	runtime.MemProfileRate = 1
    62  	defer func() {
    63  		runtime.MemProfileRate = oldRate
    64  	}()
    65  
    66  	// Allocate a meg to ensure that mcache.next_sample is updated to 1.
    67  	for i := 0; i < 1024; i++ {
    68  		memSink = make([]byte, 1024)
    69  	}
    70  
    71  	// Do the interesting allocations.
    72  	allocateTransient1M()
    73  	allocateTransient2M()
    74  	allocatePersistent1K()
    75  	allocateReflect()
    76  	memSink = nil
    77  
    78  	runtime.GC() // materialize stats
    79  	var buf bytes.Buffer
    80  	if err := Lookup("heap").WriteTo(&buf, 1); err != nil {
    81  		t.Fatalf("failed to write heap profile: %v", err)
    82  	}
    83  
    84  	memoryProfilerRun++
    85  
    86  	tests := []string{
    87  		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]+
    88  #	0x[0-9,a-f]+	runtime/pprof\.allocatePersistent1K\+0x[0-9,a-f]+	.*/runtime/pprof/mprof_test\.go:40
    89  #	0x[0-9,a-f]+	runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+	.*/runtime/pprof/mprof_test\.go:74
    90  `, 32*memoryProfilerRun, 1024*memoryProfilerRun, 32*memoryProfilerRun, 1024*memoryProfilerRun),
    91  
    92  		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]+
    93  #	0x[0-9,a-f]+	runtime/pprof\.allocateTransient1M\+0x[0-9,a-f]+	.*/runtime/pprof/mprof_test.go:21
    94  #	0x[0-9,a-f]+	runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+	.*/runtime/pprof/mprof_test.go:72
    95  `, (1<<10)*memoryProfilerRun, (1<<20)*memoryProfilerRun),
    96  
    97  		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]+
    98  #	0x[0-9,a-f]+	runtime/pprof\.allocateTransient2M\+0x[0-9,a-f]+	.*/runtime/pprof/mprof_test.go:27
    99  #	0x[0-9,a-f]+	runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+	.*/runtime/pprof/mprof_test.go:73
   100  `, memoryProfilerRun, (2<<20)*memoryProfilerRun),
   101  
   102  		fmt.Sprintf(`0: 0 \[%v: %v\] @( 0x[0-9,a-f]+)+
   103  #	0x[0-9,a-f]+	runtime/pprof\.allocateReflectTransient\+0x[0-9,a-f]+	.*/runtime/pprof/mprof_test.go:48
   104  `, memoryProfilerRun, (2<<20)*memoryProfilerRun),
   105  	}
   106  
   107  	for _, test := range tests {
   108  		if !regexp.MustCompile(test).Match(buf.Bytes()) {
   109  			t.Fatalf("The entry did not match:\n%v\n\nProfile:\n%v\n", test, buf.String())
   110  		}
   111  	}
   112  }