1 // Copyright 2018 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 // This program outputs a CPU profile that includes 6 // both Go and Cgo stacks. This is used by the mapping info 7 // tests in runtime/pprof. 8 // 9 // If SETCGOTRACEBACK=1 is set, the CPU profile will includes 10 // PCs from C side but they will not be symbolized. 11 package main 12 13 /* 14 #include <stdint.h> 15 #include <stdlib.h> 16 17 int cpuHogCSalt1 = 0; 18 int cpuHogCSalt2 = 0; 19 20 void CPUHogCFunction0(int foo) { 21 int i; 22 for (i = 0; i < 100000; i++) { 23 if (foo > 0) { 24 foo *= foo; 25 } else { 26 foo *= foo + 1; 27 } 28 cpuHogCSalt2 = foo; 29 } 30 } 31 32 void CPUHogCFunction() { 33 CPUHogCFunction0(cpuHogCSalt1); 34 } 35 36 struct CgoTracebackArg { 37 uintptr_t context; 38 uintptr_t sigContext; 39 uintptr_t *buf; 40 uintptr_t max; 41 }; 42 43 void CollectCgoTraceback(void* parg) { 44 struct CgoTracebackArg* arg = (struct CgoTracebackArg*)(parg); 45 arg->buf[0] = (uintptr_t)(CPUHogCFunction0); 46 arg->buf[1] = (uintptr_t)(CPUHogCFunction); 47 arg->buf[2] = 0; 48 }; 49 */ 50 import "C" 51 52 import ( 53 "log" 54 "os" 55 "runtime" 56 "runtime/pprof" 57 "time" 58 "unsafe" 59 ) 60 61 func init() { 62 if v := os.Getenv("SETCGOTRACEBACK"); v == "1" { 63 // Collect some PCs from C-side, but don't symbolize. 64 runtime.SetCgoTraceback(0, unsafe.Pointer(C.CollectCgoTraceback), nil, nil) 65 } 66 } 67 68 func main() { 69 go cpuHogGoFunction() 70 go cpuHogCFunction() 71 runtime.Gosched() 72 73 if err := pprof.StartCPUProfile(os.Stdout); err != nil { 74 log.Fatal("can't start CPU profile: ", err) 75 } 76 time.Sleep(200 * time.Millisecond) 77 pprof.StopCPUProfile() 78 79 if err := os.Stdout.Close(); err != nil { 80 log.Fatal("can't write CPU profile: ", err) 81 } 82 } 83 84 var salt1 int 85 var salt2 int 86 87 func cpuHogGoFunction() { 88 for { 89 foo := salt1 90 for i := 0; i < 1e5; i++ { 91 if foo > 0 { 92 foo *= foo 93 } else { 94 foo *= foo + 1 95 } 96 salt2 = foo 97 } 98 runtime.Gosched() 99 } 100 } 101 102 func cpuHogCFunction() { 103 // Generates CPU profile samples including a Cgo call path. 104 for { 105 C.CPUHogCFunction() 106 runtime.Gosched() 107 } 108 } 109