mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
refactor(coderd): optimize chatdebug (#27129)
Adds a bund of optimizations to chatdebug:
In `coderd/x/chatd/chatdebug`:
- Adds a benchmark (excluding LLM and database stuff)
- Replaces string concatenation with strings.Builder when accumulating
stream parts (~105,000ns -> ~50,00ns)
- Removes double JSON encode in RecordingTransport (114,000ns ->
64,000ns)
In `coderd/util/strings`:
- Adds a benchmark for Truncate
- Removes unnecessary allocations in Truncate (~110,000ns -> 1,550ns in
truncation case, 1 alloc -> 0 allocs in no truncation case)
> 🤖 Claude helped with this.
This commit is contained in:
@@ -64,8 +64,19 @@ func Truncate(s string, n int, opts ...TruncateOption) string {
|
||||
if n < 1 {
|
||||
return ""
|
||||
}
|
||||
runes := []rune(s)
|
||||
if len(runes) <= n {
|
||||
|
||||
// Find the byte offset of the (n+1)th rune, if any; early exit
|
||||
// avoids decoding s past what's needed.
|
||||
runeCount := 0
|
||||
cutoff := -1
|
||||
for i := range s {
|
||||
runeCount++
|
||||
if runeCount > n {
|
||||
cutoff = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if cutoff < 0 {
|
||||
return s
|
||||
}
|
||||
|
||||
@@ -73,6 +84,7 @@ func Truncate(s string, n int, opts ...TruncateOption) string {
|
||||
if options&TruncateWithEllipsis != 0 {
|
||||
maxLen--
|
||||
}
|
||||
runes := []rune(s[:cutoff])
|
||||
var sb strings.Builder
|
||||
if options&TruncateWithFullWords != 0 {
|
||||
// Convert the rune-safe prefix to a string, then find
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package strings_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
@@ -32,6 +33,7 @@ func TestTruncate(t *testing.T) {
|
||||
{"foo", 1, "f", nil},
|
||||
{"foo", 0, "", nil},
|
||||
{"foo", -1, "", nil},
|
||||
{"", 5, "", nil},
|
||||
{"foo bar", 7, "foo bar", []strings.TruncateOption{strings.TruncateWithEllipsis}},
|
||||
{"foo bar", 6, "foo b…", []strings.TruncateOption{strings.TruncateWithEllipsis}},
|
||||
{"foo bar", 5, "foo …", []strings.TruncateOption{strings.TruncateWithEllipsis}},
|
||||
@@ -81,6 +83,28 @@ func TestTruncate(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkTruncate(b *testing.B) {
|
||||
b.Run("NoTruncationNeeded", func(b *testing.B) {
|
||||
s := "a short string well under the limit"
|
||||
b.ReportAllocs()
|
||||
for b.Loop() {
|
||||
strings.Truncate(s, 1000)
|
||||
}
|
||||
})
|
||||
|
||||
b.Run("ActualTruncation", func(b *testing.B) {
|
||||
var buf bytes.Buffer
|
||||
for range 2000 {
|
||||
buf.WriteString("日本語テスト word ")
|
||||
}
|
||||
s := buf.String()
|
||||
b.ReportAllocs()
|
||||
for b.Loop() {
|
||||
strings.Truncate(s, 100, strings.TruncateWithEllipsis, strings.TruncateWithFullWords)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestUISanitize(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user