From 760e5c4f1271b8813f6d2fe89e01df18dd0ececa Mon Sep 17 00:00:00 2001 From: Raphael Amorim Date: Wed, 30 Jul 2025 11:22:10 +0200 Subject: [PATCH 1/2] perf: avoid regex compilation in runtime --- internal/llm/provider/anthropic.go | 8 ++++++-- internal/llm/tools/view.go | 3 ++- internal/tui/exp/list/filterable.go | 11 ++++++++--- internal/tui/exp/list/filterable_group.go | 10 +++++++--- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/internal/llm/provider/anthropic.go b/internal/llm/provider/anthropic.go index 3de8c805b3f0cfa08b1b2bb6b60577742ce8cc1d..fbbede590b85c9ac51b3b0c058afb7b7a8ec26bc 100644 --- a/internal/llm/provider/anthropic.go +++ b/internal/llm/provider/anthropic.go @@ -21,6 +21,11 @@ import ( "github.com/charmbracelet/crush/internal/message" ) +var ( + // Pre-compiled regex for parsing context limit errors. + contextLimitRegex = regexp.MustCompile(`input length and ` + "`max_tokens`" + ` exceed context limit: (\d+) \+ (\d+) > (\d+)`) +) + type anthropicClient struct { providerOptions providerClientOptions useBedrock bool @@ -512,8 +517,7 @@ func (a *anthropicClient) handleContextLimitError(apiErr *anthropic.Error) (int, // Parse error message like: "input length and max_tokens exceed context limit: 154978 + 50000 > 200000" errorMsg := apiErr.Error() - re := regexp.MustCompile("input length and `max_tokens` exceed context limit: (\\d+) \\+ (\\d+) > (\\d+)") - matches := re.FindStringSubmatch(errorMsg) + matches := contextLimitRegex.FindStringSubmatch(errorMsg) if len(matches) != 4 { return 0, false diff --git a/internal/llm/tools/view.go b/internal/llm/tools/view.go index ae8681f63206696c942ab96e8a4df5870831058a..ee1fd6614b3fee0a0c3d65c433bb6d9e1dd6489c 100644 --- a/internal/llm/tools/view.go +++ b/internal/llm/tools/view.go @@ -306,7 +306,8 @@ func readTextFile(filePath string, offset, limit int) (string, int, error) { } } - var lines []string + // Pre-allocate slice with expected capacity + lines := make([]string, 0, limit) lineCount = offset for scanner.Scan() && len(lines) < limit { diff --git a/internal/tui/exp/list/filterable.go b/internal/tui/exp/list/filterable.go index 83a3909b6f81f41142cf3a4b6b1d7bf7b7ee8e56..4783cce3701b7a0722c13cd7b0272f3fa2875543 100644 --- a/internal/tui/exp/list/filterable.go +++ b/internal/tui/exp/list/filterable.go @@ -15,6 +15,13 @@ import ( "github.com/sahilm/fuzzy" ) +var ( + // Pre-compiled regex for checking if a string contains alphabetic characters. + alphaRegex = regexp.MustCompile(`[a-zA-Z]`) + // Pre-compiled regex for checking if a string is alphanumeric. + alphanumericRegex = regexp.MustCompile(`^[a-zA-Z0-9]*$`) +) + type FilterableItem interface { Item FilterValue() string @@ -165,8 +172,6 @@ func (f *filterableList[T]) View() string { // removes bindings that are used for search func (f *filterableList[T]) updateKeyMaps() { - alphanumeric := regexp.MustCompile("^[a-zA-Z0-9]*$") - removeLettersAndNumbers := func(bindings []string) []string { var keep []string for _, b := range bindings { @@ -177,7 +182,7 @@ func (f *filterableList[T]) updateKeyMaps() { if b == " " { continue } - m := alphanumeric.MatchString(b) + m := alphanumericRegex.MatchString(b) if !m { keep = append(keep, b) } diff --git a/internal/tui/exp/list/filterable_group.go b/internal/tui/exp/list/filterable_group.go index 88b790c678aede588956bce4df002b766646feff..91350917bdcece7fc33c6c5069aa30db74c109fc 100644 --- a/internal/tui/exp/list/filterable_group.go +++ b/internal/tui/exp/list/filterable_group.go @@ -15,6 +15,12 @@ import ( "github.com/sahilm/fuzzy" ) +var ( + // Pre-compiled regex for checking if a string is alphanumeric. + // Note: This is duplicated from filterable.go to avoid circular dependencies. + alphanumericRegexGroup = regexp.MustCompile(`^[a-zA-Z0-9]*$`) +) + type FilterableGroupList[T FilterableItem] interface { GroupedList[T] Cursor() *tea.Cursor @@ -114,8 +120,6 @@ func (f *filterableGroupList[T]) View() string { // removes bindings that are used for search func (f *filterableGroupList[T]) updateKeyMaps() { - alphanumeric := regexp.MustCompile("^[a-zA-Z0-9]*$") - removeLettersAndNumbers := func(bindings []string) []string { var keep []string for _, b := range bindings { @@ -126,7 +130,7 @@ func (f *filterableGroupList[T]) updateKeyMaps() { if b == " " { continue } - m := alphanumeric.MatchString(b) + m := alphanumericRegexGroup.MatchString(b) if !m { keep = append(keep, b) } From 3839c364d601edf602dcff50a862b993661a4b40 Mon Sep 17 00:00:00 2001 From: Raphael Amorim Date: Wed, 30 Jul 2025 11:28:25 +0200 Subject: [PATCH 2/2] fix: lint for var blocks --- internal/llm/provider/anthropic.go | 6 ++---- internal/tui/exp/list/filterable_group.go | 8 +++----- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/internal/llm/provider/anthropic.go b/internal/llm/provider/anthropic.go index fbbede590b85c9ac51b3b0c058afb7b7a8ec26bc..c65a2e95cf1077dbd1b71320501a7e63d693971f 100644 --- a/internal/llm/provider/anthropic.go +++ b/internal/llm/provider/anthropic.go @@ -21,10 +21,8 @@ import ( "github.com/charmbracelet/crush/internal/message" ) -var ( - // Pre-compiled regex for parsing context limit errors. - contextLimitRegex = regexp.MustCompile(`input length and ` + "`max_tokens`" + ` exceed context limit: (\d+) \+ (\d+) > (\d+)`) -) +// Pre-compiled regex for parsing context limit errors. +var contextLimitRegex = regexp.MustCompile(`input length and ` + "`max_tokens`" + ` exceed context limit: (\d+) \+ (\d+) > (\d+)`) type anthropicClient struct { providerOptions providerClientOptions diff --git a/internal/tui/exp/list/filterable_group.go b/internal/tui/exp/list/filterable_group.go index 91350917bdcece7fc33c6c5069aa30db74c109fc..68c833f2d0933ecae9d78c0beb28f19287abffed 100644 --- a/internal/tui/exp/list/filterable_group.go +++ b/internal/tui/exp/list/filterable_group.go @@ -15,11 +15,9 @@ import ( "github.com/sahilm/fuzzy" ) -var ( - // Pre-compiled regex for checking if a string is alphanumeric. - // Note: This is duplicated from filterable.go to avoid circular dependencies. - alphanumericRegexGroup = regexp.MustCompile(`^[a-zA-Z0-9]*$`) -) +// Pre-compiled regex for checking if a string is alphanumeric. +// Note: This is duplicated from filterable.go to avoid circular dependencies. +var alphanumericRegexGroup = regexp.MustCompile(`^[a-zA-Z0-9]*$`) type FilterableGroupList[T FilterableItem] interface { GroupedList[T]