Skip to content

Commit eb70383

Browse files
committed
Improve speed of Call.Format.
1 parent 822e2fe commit eb70383

File tree

1 file changed

+24
-14
lines changed

1 file changed

+24
-14
lines changed

stack.go

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@ package stack
1111

1212
import (
1313
"fmt"
14+
"io"
1415
"path/filepath"
1516
"runtime"
17+
"strconv"
1618
"strings"
1719
"sync"
1820
)
@@ -66,7 +68,7 @@ func (c Call) Format(s fmt.State, verb rune) {
6668

6769
switch verb {
6870
case 's', 'v':
69-
file, line := c.fn.FileLine(uintptr(c.pc))
71+
file, line := c.fn.FileLine(c.pc)
7072
switch {
7173
case s.Flag('#'):
7274
// done
@@ -90,32 +92,40 @@ func (c Call) Format(s fmt.State, verb rune) {
9092
// pkg/sub/file.go
9193
//
9294
// From this we can easily see that fn.Name() has one less path
93-
// separator than our desired output.
95+
// separator than our desired output. We count separators from the
96+
// end of the file path until it finds two more than in the
97+
// function name and then move one character forward to preserve
98+
// the initial path segment without a leading separator.
9499
const sep = "/"
95-
impCnt := strings.Count(c.fn.Name(), sep) + 1
96-
pathCnt := strings.Count(file, sep)
97-
for pathCnt > impCnt {
98-
i := strings.Index(file, sep)
100+
goal := strings.Count(c.fn.Name(), sep) + 2
101+
pathCnt := 0
102+
i := len(file)
103+
for pathCnt < goal {
104+
i = strings.LastIndex(file[:i], sep)
99105
if i == -1 {
106+
i = -len(sep)
100107
break
101108
}
102-
file = file[i+len(sep):]
103-
pathCnt--
109+
pathCnt++
104110
}
111+
// get back to 0 or trim the leading seperator
112+
file = file[i+len(sep):]
105113
default:
106114
const sep = "/"
107115
if i := strings.LastIndex(file, sep); i != -1 {
108116
file = file[i+len(sep):]
109117
}
110118
}
111-
fmt.Fprint(s, file)
119+
io.WriteString(s, file)
112120
if verb == 'v' {
113-
fmt.Fprint(s, ":", line)
121+
buf := [7]byte{':'}
122+
s.Write(strconv.AppendInt(buf[:1], int64(line), 10))
114123
}
115124

116125
case 'd':
117-
_, line := c.fn.FileLine(uintptr(c.pc))
118-
fmt.Fprint(s, line)
126+
_, line := c.fn.FileLine(c.pc)
127+
buf := [6]byte{}
128+
s.Write(strconv.AppendInt(buf[:0], int64(line), 10))
119129

120130
case 'n':
121131
name := c.fn.Name()
@@ -129,7 +139,7 @@ func (c Call) Format(s fmt.State, verb rune) {
129139
name = name[i+len(pkgSep):]
130140
}
131141
}
132-
fmt.Fprint(s, name)
142+
io.WriteString(s, name)
133143
}
134144
}
135145

@@ -146,7 +156,7 @@ func (c Call) file() string {
146156
if c.fn == nil {
147157
return "???"
148158
}
149-
file, _ := c.fn.FileLine(uintptr(c.pc))
159+
file, _ := c.fn.FileLine(c.pc)
150160
return file
151161
}
152162

0 commit comments

Comments
 (0)