summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJunegunn Choi <junegunn.c@gmail.com>2024-04-02 08:43:08 +0900
committerJunegunn Choi <junegunn.c@gmail.com>2024-04-02 08:43:08 +0900
commitc30e486b648c1540a660802a5015aeca208274fa (patch)
tree1be9cd9e2890f3ccfb2e671e89e790e9dccbffd2
parenta575c0c54b653050bdb72b4d046ef05967d95c46 (diff)
Further performance improvements by removing unnecessary copies
-rw-r--r--CHANGELOG.md5
-rw-r--r--src/ansi.go2
-rw-r--r--src/core.go10
-rw-r--r--src/tokenizer.go4
-rw-r--r--src/util/chars.go2
5 files changed, 15 insertions, 8 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d5f66a62..a91d7b04 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,7 +3,10 @@ CHANGELOG
0.49.0
------
-- Ingestion performance improved by around 40%
+- Performance improvements
+ - Ingestion performance improved by 40%
+ - `--ansi` performance improved by 50%
+ - `--with-nth` performance improved by 30%
- Added two environment variables exported to the child processes
- `FZF_PREVIEW_LABEL`
- `FZF_BORDER_LABEL`
diff --git a/src/ansi.go b/src/ansi.go
index e917a4f2..53fae954 100644
--- a/src/ansi.go
+++ b/src/ansi.go
@@ -312,7 +312,7 @@ func parseAnsiCode(s string, delimiter byte) (int, byte, string) {
// Inlined version of strconv.Atoi() that only handles positive
// integers and does not allocate on error.
code := 0
- for _, ch := range []byte(s) {
+ for _, ch := range sbytes(s) {
ch -= '0'
if ch > 9 {
return -1, delimiter, remaining
diff --git a/src/core.go b/src/core.go
index 1006109d..ae5e58bf 100644
--- a/src/core.go
+++ b/src/core.go
@@ -23,6 +23,10 @@ func ustring(data []byte) string {
return unsafe.String(unsafe.SliceData(data), len(data))
}
+func sbytes(data string) []byte {
+ return unsafe.Slice(unsafe.StringData(data), len(data))
+}
+
// Run starts fzf
func Run(opts *Options, version string, revision string) {
sort := opts.Sort > 0
@@ -52,14 +56,14 @@ func Run(opts *Options, version string, revision string) {
prevLineAnsiState = lineAnsiState
trimmed, offsets, newState := extractColor(ustring(data), lineAnsiState, nil)
lineAnsiState = newState
- return util.ToChars([]byte(trimmed)), offsets
+ return util.ToChars(sbytes(trimmed)), offsets
}
} else {
// When color is disabled but ansi option is given,
// we simply strip out ANSI codes from the input
ansiProcessor = func(data []byte) (util.Chars, *[]ansiOffset) {
trimmed, _, _ := extractColor(ustring(data), nil, nil)
- return util.ToChars([]byte(trimmed)), nil
+ return util.ToChars(sbytes(trimmed)), nil
}
}
}
@@ -106,7 +110,7 @@ func Run(opts *Options, version string, revision string) {
eventBox.Set(EvtHeader, header)
return false
}
- item.text, item.colors = ansiProcessor([]byte(transformed))
+ item.text, item.colors = ansiProcessor(sbytes(transformed))
item.text.TrimTrailingWhitespaces()
item.text.Index = itemIndex
item.origText = &data
diff --git a/src/tokenizer.go b/src/tokenizer.go
index 9f9e2c19..defe8cce 100644
--- a/src/tokenizer.go
+++ b/src/tokenizer.go
@@ -91,7 +91,7 @@ func withPrefixLengths(tokens []string, begin int) []Token {
prefixLength := begin
for idx := range tokens {
- chars := util.ToChars([]byte(tokens[idx]))
+ chars := util.ToChars(sbytes(tokens[idx]))
ret[idx] = Token{&chars, int32(prefixLength)}
prefixLength += chars.Length()
}
@@ -187,7 +187,7 @@ func Transform(tokens []Token, withNth []Range) []Token {
if r.begin == r.end {
idx := r.begin
if idx == rangeEllipsis {
- chars := util.ToChars([]byte(joinTokens(tokens)))
+ chars := util.ToChars(sbytes(joinTokens(tokens)))
parts = append(parts, &chars)
} else {
if idx < 0 {
diff --git a/src/util/chars.go b/src/util/chars.go
index 41de9243..f946da82 100644
--- a/src/util/chars.go
+++ b/src/util/chars.go
@@ -163,7 +163,7 @@ func (chars *Chars) ToString() string {
if runes := chars.optionalRunes(); runes != nil {
return string(runes)
}
- return string(chars.slice)
+ return unsafe.String(unsafe.SliceData(chars.slice), len(chars.slice))
}
func (chars *Chars) ToRunes() []rune {