Skip to content

Commit

Permalink
test/e2e/framework/log: optimize PrunedStack()
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
kolyshkin committed Feb 20, 2020
1 parent 3ed0f1b commit 78e98da
Showing 1 changed file with 14 additions and 9 deletions.
23 changes: 14 additions & 9 deletions test/e2e/framework/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ limitations under the License.
package framework

import (
"bytes"
"fmt"
"regexp"
"runtime/debug"
"strings"
"time"

"github.com/onsi/ginkgo"
Expand Down Expand Up @@ -78,12 +78,14 @@ var codeFilterRE = regexp.MustCompile(`/github.com/onsi/ginkgo/`)
// This is a modified copy of PruneStack in https://github.com/onsi/ginkgo/blob/f90f37d87fa6b1dd9625e2b1e83c23ffae3de228/internal/codelocation/code_location.go#L25:
// - simplified API and thus renamed (calls debug.Stack() instead of taking a parameter)
// - source code filtering updated to be specific to Kubernetes
func PrunedStack(skip int) string {
fullStackTrace := string(debug.Stack())
stack := strings.Split(fullStackTrace, "\n")
// - optimized to use bytes and in-place slice filtering from
// https://github.com/golang/go/wiki/SliceTricks#filter-in-place
func PrunedStack(skip int) []byte {
fullStackTrace := debug.Stack()
stack := bytes.Split(fullStackTrace, []byte("\n"))
// Ensure that the even entries are the method names and the
// the odd entries the source code information.
if len(stack) > 0 && strings.HasPrefix(stack[0], "goroutine ") {
if len(stack) > 0 && bytes.HasPrefix(stack[0], []byte("goroutine ")) {
// Ignore "goroutine 29 [running]:" line.
stack = stack[1:]
}
Expand All @@ -94,13 +96,16 @@ func PrunedStack(skip int) string {
if len(stack) > 2*skip {
stack = stack[2*skip:]
}
prunedStack := []string{}
n := 0
for i := 0; i < len(stack)/2; i++ {
// We filter out based on the source code file name.
if !codeFilterRE.Match([]byte(stack[i*2+1])) {
prunedStack = append(prunedStack, stack[i*2])
prunedStack = append(prunedStack, stack[i*2+1])
stack[n] = stack[i*2]
stack[n+1] = stack[i*2+1]
n += 2
}
}
return strings.Join(prunedStack, "\n")
stack = stack[:n]

return bytes.Join(stack, []byte("\n"))
}

0 comments on commit 78e98da

Please sign in to comment.