diff --git a/.jules/bolt.md b/.jules/bolt.md index 40193998b..80e90d5aa 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -1,3 +1,6 @@ ## 2024-05-24 - Single Pass String Iteration for Token Estimation **Learning:** `utf8.RuneCountInString(msg)` performs a full iteration over the string. If the string needs to be iterated over again (e.g., `for _, r := range msg`) to check specific rune properties, this results in two full passes over the string. -**Action:** Always count the total number of runes manually within the existing `for range` loop when a subsequent full iteration of the string is already required. This essentially halves the execution time. \ No newline at end of file +**Action:** Always count the total number of runes manually within the existing `for range` loop when a subsequent full iteration of the string is already required. This essentially halves the execution time. +## 2024-05-25 - Efficient String Building in Loops +**Learning:** In Go, string concatenation (`+=`) in a loop leads to $O(N^2)$ complexity due to immutability. Using `strings.Builder` provides $O(N)$ efficiency. Additionally, `fmt.Fprintf` has overhead due to format string parsing; direct `sb.WriteString` calls are significantly faster. +**Action:** Use `strings.Builder` for building strings in loops and prefer direct `WriteString` calls over `fmt.Fprintf` for maximum performance in hot paths. diff --git a/pkg/channels/discord/discord.go b/pkg/channels/discord/discord.go index 661378f85..7472b0a12 100644 --- a/pkg/channels/discord/discord.go +++ b/pkg/channels/discord/discord.go @@ -406,6 +406,8 @@ func (c *DiscordChannel) handleMessage(s *discordgo.Session, m *discordgo.Messag return localPath // fallback } + var contentBuilder strings.Builder + contentBuilder.WriteString(content) for _, attachment := range m.Attachments { isAudio := utils.IsAudioFile(attachment.Filename, attachment.ContentType) @@ -413,21 +415,36 @@ func (c *DiscordChannel) handleMessage(s *discordgo.Session, m *discordgo.Messag localPath := c.downloadAttachment(attachment.URL, attachment.Filename) if localPath != "" { mediaPaths = append(mediaPaths, storeMedia(localPath, attachment.Filename)) - content = appendContent(content, fmt.Sprintf("[audio: %s]", attachment.Filename)) + if contentBuilder.Len() > 0 { + contentBuilder.WriteByte('\n') + } + contentBuilder.WriteString("[audio: ") + contentBuilder.WriteString(attachment.Filename) + contentBuilder.WriteByte(']') } else { logger.WarnCF("discord", "Failed to download audio attachment", map[string]any{ "url": attachment.URL, "filename": attachment.Filename, }) mediaPaths = append(mediaPaths, attachment.URL) - content = appendContent(content, fmt.Sprintf("[attachment: %s]", attachment.URL)) + if contentBuilder.Len() > 0 { + contentBuilder.WriteByte('\n') + } + contentBuilder.WriteString("[attachment: ") + contentBuilder.WriteString(attachment.URL) + contentBuilder.WriteByte(']') } } else { mediaPaths = append(mediaPaths, attachment.URL) - content = appendContent(content, fmt.Sprintf("[attachment: %s]", attachment.URL)) + if contentBuilder.Len() > 0 { + contentBuilder.WriteByte('\n') + } + contentBuilder.WriteString("[attachment: ") + contentBuilder.WriteString(attachment.URL) + contentBuilder.WriteByte(']') } } - + content = contentBuilder.String() if content == "" && len(mediaPaths) == 0 { return } @@ -600,7 +617,10 @@ func (c *DiscordChannel) resolveDiscordRefs(s *discordgo.Session, text string, g if msg.Author != nil { author = msg.Author.Username } - fmt.Fprintf(&sb, "\n[linked message from %s]: %s", author, msg.Content) + sb.WriteString("\n[linked message from ") + sb.WriteString(author) + sb.WriteString("]: ") + sb.WriteString(msg.Content) } return sb.String()