Skip to content

Commit c72b6d4

Browse files
MatchVersionedFile: speed (#19522)
<img width="2054" height="328" alt="Screenshot 2026-02-27 at 16 07 01" src="https://github.com/user-attachments/assets/37bfc853-bccb-4083-a494-8c989e06ca08" />
1 parent b82a7fd commit c72b6d4

File tree

2 files changed

+42
-6
lines changed

2 files changed

+42
-6
lines changed

db/version/file_version.go

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -229,19 +229,36 @@ func MatchVersionedFile(filePattern string, dirEntries []string, dir string) (st
229229
var bestVersion Version
230230
found := false
231231

232-
for _, name := range dirEntries {
233-
matched, err := filepath.Match(filePattern, name)
234-
if err != nil {
235-
return "", Version{}, false, fmt.Errorf("invalid pattern: %w", err)
236-
}
237-
if matched {
232+
// Optimization: patterns like "*-accounts.0-1.kv" are common — a single leading wildcard
233+
// followed by a literal suffix. Use HasSuffix instead of filepath.Match (which is ~50x slower).
234+
if strings.HasPrefix(filePattern, "*") && !strings.ContainsAny(filePattern[1:], "*?[") {
235+
suffix := filePattern[1:]
236+
for _, name := range dirEntries {
237+
if !strings.HasSuffix(name, suffix) {
238+
continue
239+
}
238240
ver, _ := ParseVersion(name)
239241
if !found || ver.Greater(bestVersion) {
240242
bestVersion = ver
241243
bestMatch = name
242244
found = true
243245
}
244246
}
247+
} else {
248+
for _, name := range dirEntries {
249+
matched, err := filepath.Match(filePattern, name)
250+
if err != nil {
251+
return "", Version{}, false, fmt.Errorf("invalid pattern: %w", err)
252+
}
253+
if matched {
254+
ver, _ := ParseVersion(name)
255+
if !found || ver.Greater(bestVersion) {
256+
bestVersion = ver
257+
bestMatch = name
258+
found = true
259+
}
260+
}
261+
}
245262
}
246263

247264
if !found {

db/version/file_version_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package version
22

33
import (
4+
"fmt"
45
"os"
56
"path/filepath"
67
"reflect"
@@ -400,3 +401,21 @@ func TestMatchVersionedFile_DifferentSegAndIdxNames(t *testing.T) {
400401
t.Fatal("expected ok == false for non-existent file type")
401402
}
402403
}
404+
405+
func BenchmarkMatchVersionedFile(b *testing.B) {
406+
// Simulate a large directory with thousands of snapshot files (realistic scenario)
407+
dirEntries := make([]string, 0, 2000)
408+
for i := 0; i < 500; i++ {
409+
dirEntries = append(dirEntries,
410+
fmt.Sprintf("v1.0-accounts.%d-%d.kv", i, i+1),
411+
fmt.Sprintf("v1.0-storage.%d-%d.kv", i, i+1),
412+
fmt.Sprintf("v1.0-accounts.%d-%d.kvi", i, i+1),
413+
fmt.Sprintf("v1.0-storage.%d-%d.kvi", i, i+1),
414+
)
415+
}
416+
417+
b.ResetTimer()
418+
for i := 0; i < b.N; i++ {
419+
_, _, _, _ = MatchVersionedFile("*-accounts.0-1.kvi", dirEntries, "/tmp")
420+
}
421+
}

0 commit comments

Comments
 (0)