1 // Copyright 2016 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.
9 "internal/pprof/profile"
17 // TestSampledHeapAllocProfile tests encoding of a memory profile from
18 // runtime.MemProfileRecord data.
19 func TestSampledHeapAllocProfile(t
*testing
.T
) {
20 if runtime
.GOOS
!= "linux" {
21 t
.Skip("Test requires a system with /proc/self/maps")
24 // Figure out two addresses from /proc/self/maps.
25 mmap
, err
:= ioutil
.ReadFile("/proc/self/maps")
27 t
.Fatal("Cannot read /proc/self/maps")
29 rd
:= bytes
.NewReader(mmap
)
30 mprof
:= &profile
.Profile
{}
31 if err
= mprof
.ParseMemoryMap(rd
); err
!= nil {
32 t
.Fatalf("Cannot parse /proc/self/maps")
34 if len(mprof
.Mapping
) < 2 {
35 // It is possible for a binary to only have 1 executable
37 t
.Skipf("need 2 or more mappings, got %v", len(mprof
.Mapping
))
39 address1
:= mprof
.Mapping
[0].Start
40 address2
:= mprof
.Mapping
[1].Start
44 rec
, rate
:= testMemRecords(address1
, address2
)
45 p
:= EncodeMemProfile(rec
, rate
, time
.Now())
46 if err
:= p
.Write(&buf
); err
!= nil {
47 t
.Fatalf("Failed to write profile: %v", err
)
50 p
, err
= profile
.Parse(&buf
)
52 t
.Fatalf("Could not parse Profile profile: %v", err
)
55 // Expected PeriodType, SampleType and Sample.
56 expectedPeriodType
:= &profile
.ValueType
{Type
: "space", Unit
: "bytes"}
57 expectedSampleType
:= []*profile
.ValueType
{
58 {Type
: "alloc_objects", Unit
: "count"},
59 {Type
: "alloc_space", Unit
: "bytes"},
60 {Type
: "inuse_objects", Unit
: "count"},
61 {Type
: "inuse_space", Unit
: "bytes"},
63 // Expected samples, with values unsampled according to the profiling rate.
64 expectedSample
:= []*profile
.Sample
{
65 {Value
: []int64{2050, 2099200, 1537, 1574400}, Location
: []*profile
.Location
{
66 {ID
: 1, Mapping
: mprof
.Mapping
[0], Address
: address1
},
67 {ID
: 2, Mapping
: mprof
.Mapping
[1], Address
: address2
},
69 {Value
: []int64{1, 829411, 1, 829411}, Location
: []*profile
.Location
{
70 {ID
: 3, Mapping
: mprof
.Mapping
[1], Address
: address2
+ 1},
71 {ID
: 4, Mapping
: mprof
.Mapping
[1], Address
: address2
+ 2},
73 {Value
: []int64{1, 829411, 0, 0}, Location
: []*profile
.Location
{
74 {ID
: 5, Mapping
: mprof
.Mapping
[0], Address
: address1
+ 1},
75 {ID
: 6, Mapping
: mprof
.Mapping
[0], Address
: address1
+ 2},
76 {ID
: 7, Mapping
: mprof
.Mapping
[1], Address
: address2
+ 3},
80 if p
.Period
!= 512*1024 {
81 t
.Fatalf("Sampling periods do not match")
83 if !reflect
.DeepEqual(p
.PeriodType
, expectedPeriodType
) {
84 t
.Fatalf("Period types do not match")
86 if !reflect
.DeepEqual(p
.SampleType
, expectedSampleType
) {
87 t
.Fatalf("Sample types do not match")
89 if !reflect
.DeepEqual(p
.Sample
, expectedSample
) {
90 t
.Fatalf("Samples do not match: Expected: %v, Got:%v", getSampleAsString(expectedSample
),
91 getSampleAsString(p
.Sample
))
95 func testMemRecords(a1
, a2
uint64) ([]runtime
.MemProfileRecord
, int64) {
96 addr1
, addr2
:= uintptr(a1
), uintptr(a2
)
97 rate
:= int64(512 * 1024)
98 rec
:= []runtime
.MemProfileRecord
{
99 {4096, 1024, 4, 1, [32]uintptr{addr1
, addr2
}},
100 {512 * 1024, 0, 1, 0, [32]uintptr{addr2
+ 1, addr2
+ 2}},
101 {512 * 1024, 512 * 1024, 1, 1, [32]uintptr{addr1
+ 1, addr1
+ 2, addr2
+ 3}},