perf(hints): compile link patterns on first use
- commit
- d5dd8bfbffb6a8f4fc7b92a01d08103f72487d30
- author
- brice · · 2026-10-19 14:57 UTC
- parent
- 9b0b5e5
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
1 file · +15 -7
M internal/adapters/hints/ocr.go +15 -7
| @@ -168,14 +168,22 @@ func readWords(ctx context.Context, img *image.Gray) ([]OCRWord, int, error) { | |||
| 168 | 168 | return words, n, nil | |
| 169 | 169 | } | |
| 170 | 170 | ||
| 171 | - | var domainPattern = regexp.MustCompile(`(?i)^(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+([a-z]{2,24})(?::[0-9]+)?(?:[/?#]\S*)?$`) | |
| 172 | - | var schemePattern = regexp.MustCompile(`(?i)^(?:https?|htps|file|ftp):/{1,2}\S+$`) | |
| 173 | - | var emailPattern = regexp.MustCompile(`(?i)^[a-z0-9.!#$%&'*+/=?^_` + "`" + `{|}~-]+@(?:[a-z0-9-]+\.)+[a-z]{2,24}$`) | |
| 174 | - | var fileExtensions = strings.Fields("go md txt toml json yaml yml rs py js ts sh c h png jpg log conf lock mod sum html css") | |
| 171 | + | // The link patterns compile on the first OCR link check, not at process | |
| 172 | + | // start: with hint mode off nothing here costs memory or CPU. | |
| 173 | + | var domainPattern = sync.OnceValue(func() *regexp.Regexp { | |
| 174 | + | return regexp.MustCompile(`(?i)^(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+([a-z]{2,24})(?::[0-9]+)?(?:[/?#]\S*)?$`) | |
| 175 | + | }) | |
| 176 | + | var schemePattern = sync.OnceValue(func() *regexp.Regexp { return regexp.MustCompile(`(?i)^(?:https?|htps|file|ftp):/{1,2}\S+$`) }) | |
| 177 | + | var emailPattern = sync.OnceValue(func() *regexp.Regexp { | |
| 178 | + | return regexp.MustCompile(`(?i)^[a-z0-9.!#$%&'*+/=?^_` + "`" + `{|}~-]+@(?:[a-z0-9-]+\.)+[a-z]{2,24}$`) | |
| 179 | + | }) | |
| 180 | + | var fileExtensions = sync.OnceValue(func() []string { | |
| 181 | + | return strings.Fields("go md txt toml json yaml yml rs py js ts sh c h png jpg log conf lock mod sum html css") | |
| 182 | + | }) | |
| 175 | 183 | ||
| 176 | 184 | func isTextLink(text string) bool { | |
| 177 | 185 | text = strings.Trim(text, "()[]<>.,;:'\"") | |
| 178 | - | if schemePattern.MatchString(text) || (strings.HasPrefix(strings.ToLower(text), "www.") && len(text) > 4) || emailPattern.MatchString(text) { | |
| 186 | + | if schemePattern().MatchString(text) || (strings.HasPrefix(strings.ToLower(text), "www.") && len(text) > 4) || emailPattern().MatchString(text) { | |
| 179 | 187 | return true | |
| 180 | 188 | } | |
| 181 | 189 | host := text | |
| @@ -185,11 +193,11 @@ func isTextLink(text string) bool { | |||
| 185 | 193 | if ip := net.ParseIP(host); ip != nil && ip.To4() != nil { | |
| 186 | 194 | return true | |
| 187 | 195 | } | |
| 188 | - | m := domainPattern.FindStringSubmatch(text) | |
| 196 | + | m := domainPattern().FindStringSubmatch(text) | |
| 189 | 197 | if m == nil { | |
| 190 | 198 | return false | |
| 191 | 199 | } | |
| 192 | - | for _, ext := range fileExtensions { | |
| 200 | + | for _, ext := range fileExtensions() { | |
| 193 | 201 | if strings.EqualFold(m[1], ext) { | |
| 194 | 202 | return false | |
| 195 | 203 | } | |
| @@ -168,14 +168,22 @@ func readWords(ctx context.Context, img *image.Gray) ([]OCRWord, int, error) { | |||||
| 168 | return words, n, nil | 168 | return words, n, nil | ||
| 169 | } | 169 | } | ||
| 170 | 170 | ||||
| 171 | - | var domainPattern = regexp.MustCompile(`(?i)^(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+([a-z]{2,24})(?::[0-9]+)?(?:[/?#]\S*)?$`) | 171 | + | // The link patterns compile on the first OCR link check, not at process |
| 172 | - | var schemePattern = regexp.MustCompile(`(?i)^(?:https?|htps|file|ftp):/{1,2}\S+$`) | 172 | + | // start: with hint mode off nothing here costs memory or CPU. |
| 173 | - | var emailPattern = regexp.MustCompile(`(?i)^[a-z0-9.!#$%&'*+/=?^_` + "`" + `{|}~-]+@(?:[a-z0-9-]+\.)+[a-z]{2,24}$`) | 173 | + | var domainPattern = sync.OnceValue(func() *regexp.Regexp { |
| 174 | - | var fileExtensions = strings.Fields("go md txt toml json yaml yml rs py js ts sh c h png jpg log conf lock mod sum html css") | 174 | + | return regexp.MustCompile(`(?i)^(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+([a-z]{2,24})(?::[0-9]+)?(?:[/?#]\S*)?$`) |
| 175 | + | }) | |||
| 176 | + | var schemePattern = sync.OnceValue(func() *regexp.Regexp { return regexp.MustCompile(`(?i)^(?:https?|htps|file|ftp):/{1,2}\S+$`) }) | |||
| 177 | + | var emailPattern = sync.OnceValue(func() *regexp.Regexp { | |||
| 178 | + | return regexp.MustCompile(`(?i)^[a-z0-9.!#$%&'*+/=?^_` + "`" + `{|}~-]+@(?:[a-z0-9-]+\.)+[a-z]{2,24}$`) | |||
| 179 | + | }) | |||
| 180 | + | var fileExtensions = sync.OnceValue(func() []string { | |||
| 181 | + | return strings.Fields("go md txt toml json yaml yml rs py js ts sh c h png jpg log conf lock mod sum html css") | |||
| 182 | + | }) | |||
| 175 | 183 | ||||
| 176 | func isTextLink(text string) bool { | 184 | func isTextLink(text string) bool { | ||
| 177 | text = strings.Trim(text, "()[]<>.,;:'\"") | 185 | text = strings.Trim(text, "()[]<>.,;:'\"") | ||
| 178 | - | if schemePattern.MatchString(text) || (strings.HasPrefix(strings.ToLower(text), "www.") && len(text) > 4) || emailPattern.MatchString(text) { | 186 | + | if schemePattern().MatchString(text) || (strings.HasPrefix(strings.ToLower(text), "www.") && len(text) > 4) || emailPattern().MatchString(text) { |
| 179 | return true | 187 | return true | ||
| 180 | } | 188 | } | ||
| 181 | host := text | 189 | host := text | ||
| @@ -185,11 +193,11 @@ func isTextLink(text string) bool { | |||||
| 185 | if ip := net.ParseIP(host); ip != nil && ip.To4() != nil { | 193 | if ip := net.ParseIP(host); ip != nil && ip.To4() != nil { | ||
| 186 | return true | 194 | return true | ||
| 187 | } | 195 | } | ||
| 188 | - | m := domainPattern.FindStringSubmatch(text) | 196 | + | m := domainPattern().FindStringSubmatch(text) |
| 189 | if m == nil { | 197 | if m == nil { | ||
| 190 | return false | 198 | return false | ||
| 191 | } | 199 | } | ||
| 192 | - | for _, ext := range fileExtensions { | 200 | + | for _, ext := range fileExtensions() { |
| 193 | if strings.EqualFold(m[1], ext) { | 201 | if strings.EqualFold(m[1], ext) { | ||
| 194 | return false | 202 | return false | ||
| 195 | } | 203 | } | ||