Skip to content

Commit 344948d

Browse files
committed
Simplify.
- Allocate temp buffers locally instead of with sync.Pool, just as fast, and causes fewer heap allocs. - Call findSigpanic during init rather than from sync.Once.
1 parent 3a94fa4 commit 344948d

File tree

4 files changed

+56
-81
lines changed

4 files changed

+56
-81
lines changed

stack.go

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import (
1616
"runtime"
1717
"strconv"
1818
"strings"
19-
"sync"
2019
)
2120

2221
// Call records a single function invocation from a goroutine stack.
@@ -193,16 +192,15 @@ func findSigpanic() *runtime.Func {
193192
func() int {
194193
defer func() {
195194
if p := recover(); p != nil {
196-
pcs := getUintptrs()
197-
n := runtime.Callers(2, pcs)
195+
var pcs [512]uintptr
196+
n := runtime.Callers(2, pcs[:])
198197
for _, pc := range pcs[:n] {
199198
f := runtime.FuncForPC(pc)
200199
if f.Name() == "runtime.sigpanic" {
201200
fn = f
202201
break
203202
}
204203
}
205-
putUintptrs(pcs)
206204
}
207205
}()
208206
// intentional division by zero fault
@@ -212,20 +210,12 @@ func findSigpanic() *runtime.Func {
212210
return fn
213211
}
214212

215-
var (
216-
sigpanic *runtime.Func
217-
spOnce sync.Once
218-
)
213+
var sigpanic = findSigpanic()
219214

220215
// Trace returns a CallStack for the current goroutine with element 0
221216
// identifying the calling function.
222217
func Trace() CallStack {
223-
spOnce.Do(func() {
224-
sigpanic = findSigpanic()
225-
})
226-
227218
var pcs [512]uintptr
228-
229219
n := runtime.Callers(2, pcs[:])
230220
cs := make([]Call, n)
231221

stack12.go

Lines changed: 0 additions & 27 deletions
This file was deleted.

stack13.go

Lines changed: 0 additions & 21 deletions
This file was deleted.

stack_test.go

Lines changed: 53 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -120,12 +120,6 @@ func BenchmarkCallVFmt(b *testing.B) {
120120
}
121121
}
122122

123-
func BenchmarkCallerAndVFmt(b *testing.B) {
124-
for i := 0; i < b.N; i++ {
125-
fmt.Fprint(ioutil.Discard, stack.Caller(0))
126-
}
127-
}
128-
129123
func BenchmarkCallPlusVFmt(b *testing.B) {
130124
c := stack.Caller(0)
131125
b.ResetTimer()
@@ -202,31 +196,18 @@ func BenchmarkTrace(b *testing.B) {
202196
}
203197
}
204198

205-
func BenchmarkFuncForPC(b *testing.B) {
206-
pc, _, _, _ := runtime.Caller(0)
207-
pc--
208-
var fn *runtime.Func
209-
b.ResetTimer()
210-
for i := 0; i < b.N; i++ {
211-
fn = runtime.FuncForPC(pc)
212-
}
213-
b.StopTimer()
214-
fmt.Fprint(ioutil.Discard, fn.Entry())
215-
}
216-
217199
func deepStack(depth int, b *testing.B) stack.CallStack {
218200
if depth > 0 {
219201
return deepStack(depth-1, b)
220202
}
221203
b.StartTimer()
222204
s := stack.Trace()
223-
b.StopTimer()
224205
return s
225206
}
226207

227208
func BenchmarkTrace10(b *testing.B) {
228-
b.StopTimer()
229209
for i := 0; i < b.N; i++ {
210+
b.StopTimer()
230211
deepStack(10, b)
231212
}
232213
}
@@ -244,3 +225,55 @@ func BenchmarkTrace100(b *testing.B) {
244225
deepStack(100, b)
245226
}
246227
}
228+
229+
////////////////
230+
// Benchmark functions followed by formatting
231+
////////////////
232+
233+
func BenchmarkCallerAndVFmt(b *testing.B) {
234+
for i := 0; i < b.N; i++ {
235+
fmt.Fprint(ioutil.Discard, stack.Caller(0))
236+
}
237+
}
238+
239+
func BenchmarkTraceAndVFmt(b *testing.B) {
240+
for i := 0; i < b.N; i++ {
241+
fmt.Fprint(ioutil.Discard, stack.Trace())
242+
}
243+
}
244+
245+
func BenchmarkTrace10AndVFmt(b *testing.B) {
246+
for i := 0; i < b.N; i++ {
247+
b.StopTimer()
248+
fmt.Fprint(ioutil.Discard, deepStack(10, b))
249+
}
250+
}
251+
252+
////////////////
253+
// Baseline against package runtime.
254+
////////////////
255+
256+
func BenchmarkRuntimeCaller(b *testing.B) {
257+
for i := 0; i < b.N; i++ {
258+
runtime.Caller(0)
259+
}
260+
}
261+
262+
func BenchmarkFuncForPC(b *testing.B) {
263+
pc, _, _, _ := runtime.Caller(0)
264+
pc--
265+
b.ResetTimer()
266+
for i := 0; i < b.N; i++ {
267+
runtime.FuncForPC(pc)
268+
}
269+
}
270+
271+
func BenchmarkFuncFileLine(b *testing.B) {
272+
pc, _, _, _ := runtime.Caller(0)
273+
pc--
274+
fn := runtime.FuncForPC(pc)
275+
b.ResetTimer()
276+
for i := 0; i < b.N; i++ {
277+
fn.FileLine(pc)
278+
}
279+
}

0 commit comments

Comments
 (0)