Skip to content

Commit

Permalink
Restore performance improvements from pkg#150
Browse files Browse the repository at this point in the history
  • Loading branch information
davecheney committed Jan 9, 2019
1 parent ee1923e commit e9933c1
Showing 1 changed file with 32 additions and 4 deletions.
36 changes: 32 additions & 4 deletions stack.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package errors

import (
"bytes"
"fmt"
"io"
"path"
Expand Down Expand Up @@ -98,23 +99,50 @@ type StackTrace []Frame
//
// %+v Prints filename, function, and line number for each Frame in the stack.
func (st StackTrace) Format(s fmt.State, verb rune) {
var b bytes.Buffer
switch verb {
case 'v':
switch {
case s.Flag('+'):
b.Grow(len(st) * stackMinLen)
for _, f := range st {
fmt.Fprintf(s, "\n%+v", f)
b.WriteByte('\n')
f.format(&b, s, verb)
}
case s.Flag('#'):
fmt.Fprintf(s, "%#v", []Frame(st))
fmt.Fprintf(&b, "%#v", []Frame(st))
default:
fmt.Fprintf(s, "%v", []Frame(st))
st.formatSlice(&b, s, verb)
}
case 's':
fmt.Fprintf(s, "%s", []Frame(st))
st.formatSlice(&b, s, verb)
}
io.Copy(s, &b)
}

// formatSlice will format this StackTrace into the given buffer as a slice of
// Frame, only valid when called with '%s' or '%v'.
func (st StackTrace) formatSlice(b *bytes.Buffer, s fmt.State, verb rune) {
b.WriteByte('[')
if len(st) == 0 {
b.WriteByte(']')
return
}

b.Grow(len(st) * (stackMinLen / 4))
st[0].format(b, s, verb)
for _, fr := range st[1:] {
b.WriteByte(' ')
fr.format(b, s, verb)
}
b.WriteByte(']')
}

// stackMinLen is a best-guess at the minimum length of a stack trace. It
// doesn't need to be exact, just give a good enough head start for the buffer
// to avoid the expensive early growth.
const stackMinLen = 96

// stack represents a stack of program counters.
type stack []uintptr

Expand Down

0 comments on commit e9933c1

Please sign in to comment.