]> Cypherpunks.ru repositories - gostls13.git/blob - test/finprofiled.go
cmd/compile/internal/inline: score call sites exposed by inlines
[gostls13.git] / test / finprofiled.go
1 // run
2
3 // Copyright 2015 The Go Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file.
6
7 // Test that tiny allocations with finalizers are correctly profiled.
8 // Previously profile special records could have been processed prematurely
9 // (while the object is still live).
10
11 package main
12
13 import (
14         "runtime"
15         "time"
16         "unsafe"
17 )
18
19 func main() {
20         runtime.MemProfileRate = 1
21         // Allocate 1M 4-byte objects and set a finalizer for every third object.
22         // Assuming that tiny block size is 16, some objects get finalizers setup
23         // only for middle bytes. The finalizer resurrects that object.
24         // As the result, all allocated memory must stay alive.
25         const (
26                 N             = 1 << 20
27                 tinyBlockSize = 16 // runtime._TinySize
28         )
29         hold := make([]*int32, 0, N)
30         for i := 0; i < N; i++ {
31                 x := new(int32)
32                 if i%3 == 0 {
33                         runtime.SetFinalizer(x, func(p *int32) {
34                                 hold = append(hold, p)
35                         })
36                 }
37         }
38         // Finalize as much as possible.
39         // Note: the sleep only increases probability of bug detection,
40         // it cannot lead to false failure.
41         for i := 0; i < 5; i++ {
42                 runtime.GC()
43                 time.Sleep(10 * time.Millisecond)
44         }
45         // Read memory profile.
46         var prof []runtime.MemProfileRecord
47         for {
48                 if n, ok := runtime.MemProfile(prof, false); ok {
49                         prof = prof[:n]
50                         break
51                 } else {
52                         prof = make([]runtime.MemProfileRecord, n+10)
53                 }
54         }
55         // See how much memory in tiny objects is profiled.
56         var totalBytes int64
57         for _, p := range prof {
58                 bytes := p.AllocBytes - p.FreeBytes
59                 nobj := p.AllocObjects - p.FreeObjects
60                 size := bytes / nobj
61                 if size == tinyBlockSize {
62                         totalBytes += bytes
63                 }
64         }
65         // 2*tinyBlockSize slack is for any boundary effects.
66         if want := N*int64(unsafe.Sizeof(int32(0))) - 2*tinyBlockSize; totalBytes < want {
67                 println("got", totalBytes, "want >=", want)
68                 panic("some of the tiny objects are not profiled")
69         }
70         // Just to keep hold alive.
71         if len(hold) != 0 && hold[0] == nil {
72                 panic("bad")
73         }
74 }