Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
go
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
go
Commits
b47ec598
Commit
b47ec598
authored
Mar 23, 2011
by
Russ Cox
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
runtime/pprof: cpu profiling support
R=r, bradfitzgo, r2 CC=golang-dev
https://golang.org/cl/4313041
parent
059c07ca
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
138 additions
and
1 deletion
+138
-1
src/pkg/Makefile
src/pkg/Makefile
+0
-1
src/pkg/runtime/pprof/pprof.go
src/pkg/runtime/pprof/pprof.go
+69
-0
src/pkg/runtime/pprof/pprof_test.go
src/pkg/runtime/pprof/pprof_test.go
+69
-0
No files found.
src/pkg/Makefile
View file @
b47ec598
...
...
@@ -184,7 +184,6 @@ NOTEST=\
net/dict
\
rand
\
runtime/cgo
\
runtime/pprof
\
syscall
\
testing
\
testing/iotest
\
...
...
src/pkg/runtime/pprof/pprof.go
View file @
b47ec598
...
...
@@ -14,6 +14,7 @@ import (
"io"
"os"
"runtime"
"sync"
)
// WriteHeapProfile writes a pprof-formatted heap profile to w.
...
...
@@ -105,3 +106,71 @@ func WriteHeapProfile(w io.Writer) os.Error {
}
return
b
.
Flush
()
}
var
cpu
struct
{
sync
.
Mutex
profiling
bool
done
chan
bool
}
// StartCPUProfile enables CPU profiling for the current process.
// While profiling, the profile will be buffered and written to w.
// StartCPUProfile returns an error if profiling is already enabled.
func
StartCPUProfile
(
w
io
.
Writer
)
os
.
Error
{
// The runtime routines allow a variable profiling rate,
// but in practice operating systems cannot trigger signals
// at more than about 500 Hz, and our processing of the
// signal is not cheap (mostly getting the stack trace).
// 100 Hz is a reasonable choice: it is frequent enough to
// produce useful data, rare enough not to bog down the
// system, and a nice round number to make it easy to
// convert sample counts to seconds. Instead of requiring
// each client to specify the frequency, we hard code it.
const
hz
=
100
// Avoid queueing behind StopCPUProfile.
// Could use TryLock instead if we had it.
if
cpu
.
profiling
{
return
fmt
.
Errorf
(
"cpu profiling already in use"
)
}
cpu
.
Lock
()
defer
cpu
.
Unlock
()
if
cpu
.
done
==
nil
{
cpu
.
done
=
make
(
chan
bool
)
}
// Double-check.
if
cpu
.
profiling
{
return
fmt
.
Errorf
(
"cpu profiling already in use"
)
}
cpu
.
profiling
=
true
runtime
.
SetCPUProfileRate
(
hz
)
go
profileWriter
(
w
)
return
nil
}
func
profileWriter
(
w
io
.
Writer
)
{
for
{
data
:=
runtime
.
CPUProfile
()
if
data
==
nil
{
break
}
w
.
Write
(
data
)
}
cpu
.
done
<-
true
}
// StopCPUProfile stops the current CPU profile, if any.
// StopCPUProfile only returns after all the writes for the
// profile have completed.
func
StopCPUProfile
()
{
cpu
.
Lock
()
defer
cpu
.
Unlock
()
if
!
cpu
.
profiling
{
return
}
cpu
.
profiling
=
false
runtime
.
SetCPUProfileRate
(
0
)
<-
cpu
.
done
}
src/pkg/runtime/pprof/pprof_test.go
0 → 100644
View file @
b47ec598
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package
pprof_test
import
(
"bytes"
"hash/crc32"
"runtime"
.
"runtime/pprof"
"strings"
"testing"
"unsafe"
)
func
TestCPUProfile
(
t
*
testing
.
T
)
{
if
runtime
.
GOOS
==
"windows"
||
runtime
.
GOOS
==
"plan9"
{
return
}
buf
:=
make
([]
byte
,
100000
)
var
prof
bytes
.
Buffer
if
err
:=
StartCPUProfile
(
&
prof
);
err
!=
nil
{
t
.
Fatal
(
err
)
}
// This loop takes about a quarter second on a 2 GHz laptop.
// We only need to get one 100 Hz clock tick, so we've got
// a 25x safety buffer.
for
i
:=
0
;
i
<
1000
;
i
++
{
crc32
.
ChecksumIEEE
(
buf
)
}
StopCPUProfile
()
// Convert []byte to []uintptr.
bytes
:=
prof
.
Bytes
()
val
:=
*
(
*
[]
uintptr
)(
unsafe
.
Pointer
(
&
bytes
))
val
=
val
[
:
len
(
bytes
)
/
unsafe
.
Sizeof
(
uintptr
(
0
))]
if
len
(
val
)
<
10
{
t
.
Fatalf
(
"profile too short: %#x"
,
val
)
}
if
val
[
0
]
!=
0
||
val
[
1
]
!=
3
||
val
[
2
]
!=
0
||
val
[
3
]
!=
1e6
/
100
||
val
[
4
]
!=
0
{
t
.
Fatalf
(
"unexpected header %#x"
,
val
[
:
5
])
}
// Check that profile is well formed and contains ChecksumIEEE.
found
:=
false
val
=
val
[
5
:
]
for
len
(
val
)
>
0
{
if
len
(
val
)
<
2
||
val
[
0
]
<
1
||
val
[
1
]
<
1
||
uintptr
(
len
(
val
))
<
2
+
val
[
1
]
{
t
.
Fatalf
(
"malformed profile. leftover: %#x"
,
val
)
}
for
_
,
pc
:=
range
val
[
2
:
2
+
val
[
1
]]
{
f
:=
runtime
.
FuncForPC
(
pc
)
if
f
==
nil
{
continue
}
if
strings
.
Contains
(
f
.
Name
(),
"ChecksumIEEE"
)
{
found
=
true
}
}
val
=
val
[
2
+
val
[
1
]
:
]
}
if
!
found
{
t
.
Fatal
(
"did not find ChecksumIEEE in the profile"
)
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment