perf: use strings.Builder instead of buffer

This commit is contained in:
Jan De Dobbeleer 2021-01-06 08:52:43 +01:00 committed by Jan De Dobbeleer
parent 5d6d64508d
commit 3a86f49b72
6 changed files with 22 additions and 49 deletions

View file

@ -1,7 +1,6 @@
package main
import (
"bytes"
"errors"
"fmt"
"strings"
@ -46,7 +45,7 @@ func getColorFromName(colorName string, isBackground bool) (string, error) {
// AnsiColor writes colorized strings
type AnsiColor struct {
buffer *bytes.Buffer
builder strings.Builder
formats *ansiFormats
}
@ -84,7 +83,7 @@ func (a *AnsiColor) writeColoredText(background, foreground, text string) {
fgAnsiColor := a.getAnsiFromColorString(foreground, false)
coloredText = fmt.Sprintf(a.formats.colorFull, bgAnsiColor, fgAnsiColor, text)
}
a.buffer.WriteString(coloredText)
a.builder.WriteString(coloredText)
}
func (a *AnsiColor) writeAndRemoveText(background, foreground, text, textToRemove, parentText string) string {
@ -122,9 +121,9 @@ func (a *AnsiColor) write(background, foreground, text string) {
}
func (a *AnsiColor) string() string {
return a.buffer.String()
return a.builder.String()
}
func (a *AnsiColor) reset() {
a.buffer.Reset()
a.builder.Reset()
}

View file

@ -1,7 +1,6 @@
package main
import (
"bytes"
"testing"
"github.com/gookit/color"
@ -16,7 +15,6 @@ func TestWriteAndRemoveText(t *testing.T) {
formats := &ansiFormats{}
formats.init("pwsh")
renderer := &AnsiColor{
buffer: new(bytes.Buffer),
formats: formats,
}
text := renderer.writeAndRemoveText("#193549", "#fff", "This is white, ", "This is white, ", inputText)
@ -28,7 +26,6 @@ func TestWriteAndRemoveTextColored(t *testing.T) {
formats := &ansiFormats{}
formats.init("pwsh")
renderer := &AnsiColor{
buffer: new(bytes.Buffer),
formats: formats,
}
text := renderer.writeAndRemoveText("#193549", "#ff5733", "this is orange", "<#ff5733>this is orange</>", inputText)
@ -40,7 +37,6 @@ func TestWriteColorOverride(t *testing.T) {
formats := &ansiFormats{}
formats.init("pwsh")
renderer := &AnsiColor{
buffer: new(bytes.Buffer),
formats: formats,
}
renderer.write("#193549", "#ff5733", inputText)
@ -51,7 +47,6 @@ func TestWriteColorOverrideBackground(t *testing.T) {
formats := &ansiFormats{}
formats.init("pwsh")
renderer := &AnsiColor{
buffer: new(bytes.Buffer),
formats: formats,
}
text := "This is white, <,#000000>this is black</>, white again"
@ -63,7 +58,6 @@ func TestWriteColorOverrideBackground16(t *testing.T) {
formats := &ansiFormats{}
formats.init("pwsh")
renderer := &AnsiColor{
buffer: new(bytes.Buffer),
formats: formats,
}
text := "This is default <,white> this background is changed</> default again"
@ -77,7 +71,6 @@ func TestWriteColorOverrideBoth(t *testing.T) {
formats := &ansiFormats{}
formats.init("pwsh")
renderer := &AnsiColor{
buffer: new(bytes.Buffer),
formats: formats,
}
text := "This is white, <#000000,#ffffff>this is black</>, white again"
@ -90,7 +83,6 @@ func TestWriteColorOverrideBoth16(t *testing.T) {
formats := &ansiFormats{}
formats.init("pwsh")
renderer := &AnsiColor{
buffer: new(bytes.Buffer),
formats: formats,
}
text := "This is white, <black,white>this is black</>, white again"
@ -103,7 +95,6 @@ func TestWriteColorOverrideDouble(t *testing.T) {
formats := &ansiFormats{}
formats.init("pwsh")
renderer := &AnsiColor{
buffer: new(bytes.Buffer),
formats: formats,
}
text := "<#ffffff>jan</>@<#ffffff>Jans-MBP</>"
@ -116,7 +107,6 @@ func TestWriteColorTransparent(t *testing.T) {
formats := &ansiFormats{}
formats.init("pwsh")
renderer := &AnsiColor{
buffer: new(bytes.Buffer),
formats: formats,
}
text := "This is white"
@ -128,7 +118,6 @@ func TestWriteColorName(t *testing.T) {
formats := &ansiFormats{}
formats.init("pwsh")
renderer := &AnsiColor{
buffer: new(bytes.Buffer),
formats: formats,
}
text := "This is white, <red>this is red</>, white again"
@ -140,7 +129,6 @@ func TestWriteColorInvalid(t *testing.T) {
formats := &ansiFormats{}
formats.init("pwsh")
renderer := &AnsiColor{
buffer: new(bytes.Buffer),
formats: formats,
}
text := "This is white, <invalid>this is orange</>, white again"
@ -149,41 +137,31 @@ func TestWriteColorInvalid(t *testing.T) {
}
func TestGetAnsiFromColorStringBg(t *testing.T) {
renderer := &AnsiColor{
buffer: new(bytes.Buffer),
}
renderer := &AnsiColor{}
colorCode := renderer.getAnsiFromColorString("blue", true)
assert.Equal(t, color.BgBlue.Code(), colorCode)
}
func TestGetAnsiFromColorStringFg(t *testing.T) {
renderer := &AnsiColor{
buffer: new(bytes.Buffer),
}
renderer := &AnsiColor{}
colorCode := renderer.getAnsiFromColorString("red", false)
assert.Equal(t, color.FgRed.Code(), colorCode)
}
func TestGetAnsiFromColorStringHex(t *testing.T) {
renderer := &AnsiColor{
buffer: new(bytes.Buffer),
}
renderer := &AnsiColor{}
colorCode := renderer.getAnsiFromColorString("#AABBCC", false)
assert.Equal(t, color.HEX("#AABBCC").Code(), colorCode)
}
func TestGetAnsiFromColorStringInvalidFg(t *testing.T) {
renderer := &AnsiColor{
buffer: new(bytes.Buffer),
}
renderer := &AnsiColor{}
colorCode := renderer.getAnsiFromColorString("invalid", false)
assert.Equal(t, "", colorCode)
}
func TestGetAnsiFromColorStringInvalidBg(t *testing.T) {
renderer := &AnsiColor{
buffer: new(bytes.Buffer),
}
renderer := &AnsiColor{}
colorCode := renderer.getAnsiFromColorString("invalid", true)
assert.Equal(t, "", colorCode)
}

View file

@ -1,23 +1,23 @@
package main
import (
"bytes"
"fmt"
"strings"
)
// AnsiRenderer exposes functionality using ANSI
type AnsiRenderer struct {
buffer *bytes.Buffer
builder strings.Builder
formats *ansiFormats
}
func (r *AnsiRenderer) carriageForward() {
r.buffer.WriteString(fmt.Sprintf(r.formats.left, 1000))
r.builder.WriteString(fmt.Sprintf(r.formats.left, 1000))
}
func (r *AnsiRenderer) setCursorForRightWrite(text string, offset int) {
strippedLen := r.formats.lenWithoutANSI(text) + -offset
r.buffer.WriteString(fmt.Sprintf(r.formats.right, strippedLen))
r.builder.WriteString(fmt.Sprintf(r.formats.right, strippedLen))
}
func (r *AnsiRenderer) changeLine(numberOfLines int) {
@ -26,32 +26,32 @@ func (r *AnsiRenderer) changeLine(numberOfLines int) {
position = "F"
numberOfLines = -numberOfLines
}
r.buffer.WriteString(fmt.Sprintf(r.formats.linechange, numberOfLines, position))
r.builder.WriteString(fmt.Sprintf(r.formats.linechange, numberOfLines, position))
}
func (r *AnsiRenderer) creset() {
r.buffer.WriteString(r.formats.creset)
r.builder.WriteString(r.formats.creset)
}
func (r *AnsiRenderer) print(text string) {
r.buffer.WriteString(text)
r.builder.WriteString(text)
// Due to a bug in Powershell, the end of the line needs to be cleared.
// If this doesn't happen, the portion after the prompt gets colored in the background
// color of the line above the new input line. Clearing the line fixes this,
// but can hopefully one day be removed when this is resolved natively.
if r.formats.shell == pwsh || r.formats.shell == powershell5 {
r.buffer.WriteString(r.formats.clearEOL)
r.builder.WriteString(r.formats.clearEOL)
}
}
func (r *AnsiRenderer) string() string {
return r.buffer.String()
return r.builder.String()
}
func (r *AnsiRenderer) saveCursorPosition() {
r.buffer.WriteString(r.formats.saveCursorPosition)
r.builder.WriteString(r.formats.saveCursorPosition)
}
func (r *AnsiRenderer) restoreCursorPosition() {
r.buffer.WriteString(r.formats.restoreCursorPosition)
r.builder.WriteString(r.formats.restoreCursorPosition)
}

View file

@ -202,7 +202,7 @@ func (e *engine) debug() {
e.writePowerLineSeparator(Transparent, e.activeSegment.Background, true)
}
segmentTiming.stringValue = e.color.string()
e.color.buffer.Reset()
e.color.builder.Reset()
}
segmentTimings = append(segmentTimings, segmentTiming)
}

View file

@ -3,7 +3,6 @@
package main
import (
"bytes"
"encoding/json"
"flag"
"fmt"
@ -134,11 +133,9 @@ func main() {
formats.init(env.getShellName())
renderer := &AnsiRenderer{
buffer: new(bytes.Buffer),
formats: formats,
}
colorer := &AnsiColor{
buffer: new(bytes.Buffer),
formats: formats,
}
title := &consoleTitle{

View file

@ -1,7 +1,6 @@
package main
import (
"bytes"
"fmt"
"path/filepath"
"sort"
@ -70,7 +69,7 @@ func (pt *path) init(props *properties, env environmentInfo) {
}
func (pt *path) getAgnosterPath() string {
buffer := new(bytes.Buffer)
var buffer strings.Builder
pwd := pt.getPwd()
buffer.WriteString(pt.rootLocation())
pathDepth := pt.pathDepth(pwd)