Skip to content

Commit 78e98da

Browse files
committed
test/e2e/framework/log: optimize PrunedStack()
Use bytes instead of strings, and slice in-place filter (see https://github.com/golang/go/wiki/SliceTricks#filter-in-place) to avoid copying strings around. In my benchmark it shows almost 2x improvement: BenchmarkString-8 1477207 10198 ns/op BenchmarkBuffer-8 1561291 7622 ns/op BenchmarkInPlace-8 2295714 5202 ns/op String is the original implementation, Buffer is an intermediary one that uses strings.Builder, and InPlace is the one from this commit. Signed-off-by: Kir Kolyshkin <[email protected]>
1 parent 3ed0f1b commit 78e98da

File tree

1 file changed

+14
-9
lines changed

1 file changed

+14
-9
lines changed

test/e2e/framework/log.go

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ limitations under the License.
1717
package framework
1818

1919
import (
20+
"bytes"
2021
"fmt"
2122
"regexp"
2223
"runtime/debug"
23-
"strings"
2424
"time"
2525

2626
"github.com/onsi/ginkgo"
@@ -78,12 +78,14 @@ var codeFilterRE = regexp.MustCompile(`/github.com/onsi/ginkgo/`)
7878
// This is a modified copy of PruneStack in https://github.com/onsi/ginkgo/blob/f90f37d87fa6b1dd9625e2b1e83c23ffae3de228/internal/codelocation/code_location.go#L25:
7979
// - simplified API and thus renamed (calls debug.Stack() instead of taking a parameter)
8080
// - source code filtering updated to be specific to Kubernetes
81-
func PrunedStack(skip int) string {
82-
fullStackTrace := string(debug.Stack())
83-
stack := strings.Split(fullStackTrace, "\n")
81+
// - optimized to use bytes and in-place slice filtering from
82+
// https://github.com/golang/go/wiki/SliceTricks#filter-in-place
83+
func PrunedStack(skip int) []byte {
84+
fullStackTrace := debug.Stack()
85+
stack := bytes.Split(fullStackTrace, []byte("\n"))
8486
// Ensure that the even entries are the method names and the
8587
// the odd entries the source code information.
86-
if len(stack) > 0 && strings.HasPrefix(stack[0], "goroutine ") {
88+
if len(stack) > 0 && bytes.HasPrefix(stack[0], []byte("goroutine ")) {
8789
// Ignore "goroutine 29 [running]:" line.
8890
stack = stack[1:]
8991
}
@@ -94,13 +96,16 @@ func PrunedStack(skip int) string {
9496
if len(stack) > 2*skip {
9597
stack = stack[2*skip:]
9698
}
97-
prunedStack := []string{}
99+
n := 0
98100
for i := 0; i < len(stack)/2; i++ {
99101
// We filter out based on the source code file name.
100102
if !codeFilterRE.Match([]byte(stack[i*2+1])) {
101-
prunedStack = append(prunedStack, stack[i*2])
102-
prunedStack = append(prunedStack, stack[i*2+1])
103+
stack[n] = stack[i*2]
104+
stack[n+1] = stack[i*2+1]
105+
n += 2
103106
}
104107
}
105-
return strings.Join(prunedStack, "\n")
108+
stack = stack[:n]
109+
110+
return bytes.Join(stack, []byte("\n"))
106111
}

0 commit comments

Comments
 (0)