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:
Cian Johnston
2026-08-05 11:59:37 +01:00
committed by GitHub
parent 05baba1e63
commit c62079c053
8 changed files with 664 additions and 101 deletions
+14 -2
View File
@@ -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
+24
View File
@@ -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()