From cd434a05fe81deec2256235e4a2e3057895b55c0 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Mon, 19 Jan 2026 15:15:20 +0100 Subject: pkg/aflow: cache disk usage in Cache Calculating total disk usage of all cache entries can take very long time for large caches (needs to stat all files). This is especially problematic for tools/syz-aflow. Cache disk usage in the meta file. --- pkg/aflow/cache.go | 46 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/pkg/aflow/cache.go b/pkg/aflow/cache.go index fe60e5358..a3eb8005e 100644 --- a/pkg/aflow/cache.go +++ b/pkg/aflow/cache.go @@ -4,6 +4,7 @@ package aflow import ( + "encoding/json" "fmt" "maps" "os" @@ -88,7 +89,11 @@ func (c *Cache) Create(typ, desc string, populate func(string) error) (string, e if err != nil { return "", err } - if err := osutil.WriteFile(metaFile, []byte(desc)); err != nil { + meta := cacheMeta{ + Description: desc, + DiskUsage: size, + } + if err := osutil.WriteJSON(metaFile, meta); err != nil { os.RemoveAll(dir) return "", err } @@ -135,26 +140,42 @@ func (c *Cache) init() error { } for _, dir := range dirs { metaFile := filepath.Join(dir, cacheMetaFile) - if !osutil.IsExist(metaFile) { - if err := osutil.RemoveAll(dir); err != nil { + data, err := os.ReadFile(metaFile) + if err != nil { + if os.IsNotExist(err) { + // Incomplete cache dir. + if err := osutil.RemoveAll(dir); err != nil { + return err + } + continue + } + return err + } + var meta cacheMeta + if err := json.Unmarshal(data, &meta); err != nil { + // Assume the old format that contained just the description. + // This code can be removed after 2027-06-01, + // and the code above can use osutil.ReadJSON. + size, err := osutil.DiskUsage(dir) + if err != nil { + return err + } + meta.Description = string(data) + meta.DiskUsage = size + if err := osutil.WriteJSON(metaFile, meta); err != nil { return err } - continue } stat, err := os.Stat(metaFile) if err != nil { return err } - size, err := osutil.DiskUsage(dir) - if err != nil { - return err - } c.entries[dir] = &cacheEntry{ dir: dir, - size: size, + size: meta.DiskUsage, lastUsed: stat.ModTime(), } - c.currentSize += size + c.currentSize += meta.DiskUsage } c.mu.Lock() defer c.mu.Unlock() @@ -198,4 +219,9 @@ func (c *Cache) logf(msg string, args ...any) { } } +type cacheMeta struct { + Description string + DiskUsage uint64 +} + const cacheMetaFile = "aflow-meta" -- cgit mrf-deployment