diff options
| author | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-09-17 14:17:54 +0200 |
|---|---|---|
| committer | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-09-17 14:17:54 +0200 |
| commit | b66850cc8c584cc00bcd796eb3aa238bcf87394a (patch) | |
| tree | 3f922d30071e2187e0c2f123e00f57e250792da6 /internal/engine/facts.go | |
| parent | f74a02254ac15a84d38c9a254ead293ebaad2377 (diff) | |
| download | krino-b66850cc8c584cc00bcd796eb3aa238bcf87394a.tar.gz krino-b66850cc8c584cc00bcd796eb3aa238bcf87394a.zip | |
a file's name is folded once, not once per name test
Folding is the expensive half of a name test on a name with diacritics,
and every name test of every rule folded the same name again: on Polish
names it was most of the matching work. The per-file facts memoise it,
which is where one file's work belongs - the object is per file and per
goroutine, so no lock.
4000 Polish names, twelve rules with name tests: 0.33s -> 0.13s
Diffstat (limited to 'internal/engine/facts.go')
| -rw-r--r-- | internal/engine/facts.go | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/internal/engine/facts.go b/internal/engine/facts.go index 6540fdd..d20a34d 100644 --- a/internal/engine/facts.go +++ b/internal/engine/facts.go @@ -179,6 +179,10 @@ type facts struct { // absolute, for a front end that offers to act on the other copy. dupOriginal string + // folded memoises the folded form of this file's name and path, which + // every name test of every rule would otherwise recompute. + folded map[string]norm.Folded + contentDone bool // extraction was attempted contentErr error // why it failed partialErr error // extract.ErrPartial: a keyword not found may be in the unread part @@ -192,6 +196,21 @@ func newFacts(run *matchRun, file scan.File) *facts { return &facts{run: run, file: file} } +// Folded is the file's name or path folded for comparison, worked out once +// however many name tests ask for it. facts belongs to one file and one +// goroutine, so no lock is needed. +func (f *facts) Folded(subj string) norm.Folded { + if v, ok := f.folded[subj]; ok { + return v + } + v := norm.FoldMapped(subj) + if f.folded == nil { + f.folded = make(map[string]norm.Folded, 2) + } + f.folded[subj] = v + return v +} + func (f *facts) Name() string { return f.file.Name } func (f *facts) Rel() string { return f.file.Rel } func (f *facts) Size() int64 { return f.file.Size } |
