Home | History | Annotate | Download | only in testprogcgo
      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.
      4 
      5 package main
      6 
      7 // Run a slow C function saving a CPU profile.
      8 
      9 /*
     10 #include <stdint.h>
     11 
     12 int salt1;
     13 int salt2;
     14 
     15 void cpuHog() {
     16 	int foo = salt1;
     17 	int i;
     18 
     19 	for (i = 0; i < 100000; i++) {
     20 		if (foo > 0) {
     21 			foo *= foo;
     22 		} else {
     23 			foo *= foo + 1;
     24 		}
     25 	}
     26 	salt2 = foo;
     27 }
     28 
     29 static int cpuHogCount;
     30 
     31 struct cgoTracebackArg {
     32 	uintptr_t  context;
     33 	uintptr_t  sigContext;
     34 	uintptr_t* buf;
     35 	uintptr_t  max;
     36 };
     37 
     38 // pprofCgoTraceback is passed to runtime.SetCgoTraceback.
     39 // For testing purposes it pretends that all CPU hits in C code are in cpuHog.
     40 void pprofCgoTraceback(void* parg) {
     41 	struct cgoTracebackArg* arg = (struct cgoTracebackArg*)(parg);
     42 	arg->buf[0] = (uintptr_t)(cpuHog) + 0x10;
     43 	arg->buf[1] = 0;
     44 	++cpuHogCount;
     45 }
     46 
     47 // getCpuHogCount fetches the number of times we've seen cpuHog in the
     48 // traceback.
     49 int getCpuHogCount() {
     50 	return cpuHogCount;
     51 }
     52 */
     53 import "C"
     54 
     55 import (
     56 	"fmt"
     57 	"io/ioutil"
     58 	"os"
     59 	"runtime"
     60 	"runtime/pprof"
     61 	"time"
     62 	"unsafe"
     63 )
     64 
     65 func init() {
     66 	register("CgoPprof", CgoPprof)
     67 }
     68 
     69 func CgoPprof() {
     70 	runtime.SetCgoTraceback(0, unsafe.Pointer(C.pprofCgoTraceback), nil, nil)
     71 
     72 	f, err := ioutil.TempFile("", "prof")
     73 	if err != nil {
     74 		fmt.Fprintln(os.Stderr, err)
     75 		os.Exit(2)
     76 	}
     77 
     78 	if err := pprof.StartCPUProfile(f); err != nil {
     79 		fmt.Fprintln(os.Stderr, err)
     80 		os.Exit(2)
     81 	}
     82 
     83 	t0 := time.Now()
     84 	for C.getCpuHogCount() < 2 && time.Since(t0) < time.Second {
     85 		C.cpuHog()
     86 	}
     87 
     88 	pprof.StopCPUProfile()
     89 
     90 	name := f.Name()
     91 	if err := f.Close(); err != nil {
     92 		fmt.Fprintln(os.Stderr, err)
     93 		os.Exit(2)
     94 	}
     95 
     96 	fmt.Println(name)
     97 }
     98