Artifact c802f786eaa3ddecd63853c74dcb784531e5deb54730748a93cdb95d2d43db24:
- File
internal/content/cache_sized_test.go
— part of check-in
[94f61db228]
at
2026-10-26 00:02:06
on branch main
— perf(manifest): memoize parsed sub-manifests by hash
draft-fossil-submanifests-00 ยง7.4: enumeration results SHOULD be cached keyed by artifact name, so a rebuild parses each distinct sub-manifest once. The tree walk's loader now serves a resolved node from, and keeps it in, a new byte-bounded LRU memo on content.Cache (DerivedSized), keyed by the node's hash and charged its bytes, within a quarter of the cache's budget. The existing 32-entry Derived FIFO is sized for a few parsed check-ins; a tree's working set is every distinct node, which would thrash it and evict those check-ins.
Only a node that resolved is kept, so a phantom is looked up afresh and fails the walk as before. Depth, cycle and node-count bounds stay per walk. The memo is dropped with Derived on Invalidate and Clear, and the Repo's cache is replaced at every write.
Listing a tree that differs from one already read in one leaf now parses its manifest and that leaf; listing every check-in of zit's recorded tree history parses 48 sub-manifests instead of 109. SM-7.4-1 is covered.
Tracked in #493. (user: [email protected], size: 1790) [annotate] [blame] [check-ins using] [more...]
package content import "testing" func TestCacheDerivedSized(t *testing.T) { var nilCache *Cache nilCache.SetDerivedSized("k", 1, 1) if _, ok := nilCache.DerivedSized("k"); ok { t.Fatal("nil cache held a sized value") } c := NewCache(400) // a sized budget of 100 if _, ok := c.DerivedSized("k"); ok { t.Fatal("empty cache held a sized value") } c.SetDerivedSized("a", "A", 40) c.SetDerivedSized("b", "B", 40) if v, ok := c.DerivedSized("a"); !ok || v != "A" { t.Fatalf("DerivedSized(a) = %v, %v; want A, true", v, ok) } // a was read last, so b is the least recently used and goes first. c.SetDerivedSized("c", "C", 40) if _, ok := c.DerivedSized("b"); ok { t.Fatal("the least recently used value survived past the byte budget") } for _, k := range []string{"a", "c"} { if _, ok := c.DerivedSized(k); !ok { t.Fatalf("DerivedSized(%s) evicted within the budget", k) } } // A value larger than the whole budget is not kept, and evicts nothing. c.SetDerivedSized("huge", "H", 101) if _, ok := c.DerivedSized("huge"); ok { t.Fatal("a value over the budget was kept") } if _, ok := c.DerivedSized("a"); !ok { t.Fatal("an over-budget value evicted a held one") } // Re-setting a held key replaces it without counting a store. c.SetDerivedSized("a", "A2", 40) st := c.Stats() if st.SizedStores != 3 || st.SizedHits != 4 { t.Fatalf("SizedStores = %d, SizedHits = %d; want 3, 4", st.SizedStores, st.SizedHits) } if v, _ := c.DerivedSized("a"); v != "A2" { t.Fatalf("DerivedSized(a) = %v after re-setting it", v) } c.Invalidate(1) if _, ok := c.DerivedSized("a"); ok { t.Fatal("Invalidate kept a sized value") } c.SetDerivedSized("a", "A", 40) c.Clear() if _, ok := c.DerivedSized("a"); ok { t.Fatal("Clear kept a sized value") } }