From 78d8313791f05defc9e0a9f2bad8e9710f741a60 Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Thu, 17 Sep 2026 13:50:01 +0200 Subject: the suffix search continues instead of starting again at _1 Every file renamed onto one name probed stem_1, stem_2, ... from the beginning, so N files cost N^2/2 Exists calls - a test here counts 1890 of them for 60 files. The search now continues from the highest suffix already tried for that stem. Within one plan that is the same answer: the taken set only grows while a plan is built and the disk is not being written to, so a suffix taken once stays taken. Proved rather than argued - with same_1 and same_3 already on disk and same_2 free, both versions put a file in the gap, and the two plans are byte-identical. 1500 files renamed to one name: 2.63s -> 0.05s --- internal/plan/chain.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'internal/plan/chain.go') diff --git a/internal/plan/chain.go b/internal/plan/chain.go index b8a95f6..7c95d9b 100644 --- a/internal/plan/chain.go +++ b/internal/plan/chain.go @@ -25,13 +25,13 @@ type Claims struct { // NewClaims returns an empty Claims, ready to pass to Build. func NewClaims() *Claims { - return &Claims{taken: claimed{}} + return &Claims{taken: newClaimed()} } // Claim marks path as spoken for: a later Build call of the run treats it // as another step's result, never displacing it (spec ยง7.4). func (c *Claims) Claim(path string) { - c.taken[path] = true + c.taken.taken[path] = true } // Input is one file and the rules that matched it, in match order. @@ -80,7 +80,7 @@ func Build(root string, in []Input, now time.Time, d Disk, claims *Claims) []Cha // takes a free name there, exactly as suffix already did for a path that // exists on disk. for _, x := range in { - claims.taken[x.File.Path] = true + claims.taken.taken[x.File.Path] = true } chains := make([]Chain, len(in)) for _, i := range order { @@ -152,7 +152,7 @@ func buildOne(root string, in Input, now time.Time, d Disk, claim claimed) Chain // a name be claimed before its file has actually // vacated it - and stays; do not "fix" it by weakening // the disk check. - claim[resolved] = true + claim.taken[resolved] = true if a.Kind == config.Move { cur = resolved moves++ @@ -184,7 +184,7 @@ func buildOne(root string, in Input, now time.Time, d Disk, claim claimed) Chain step.Displaces = displaces if skip == "" { cur = resolved - claim[resolved] = true + claim.taken[resolved] = true } case config.Delete, config.DeletePermanent: -- cgit v1.3