fix(cache): stop fsync-hammering the SD card on unchanged data#402
fix(cache): stop fsync-hammering the SD card on unchanged data#402ChuckBuilds wants to merge 1 commit into
Conversation
DiskCache.set wrote every key as mkstemp -> json.dump(indent=4) -> flush+fsync -> replace -> chmod, on the persistent cache dir — dozens of force-flushed SD writes per minute on an API-heavy install, mostly rewriting identical data every plugin update cycle. - Serialize once, compact (no indent): cache files are machine-read only; indenting multiplied the bytes written. - Skip the disk when the payload for a key is unchanged (adler32 map, per-process); refresh the file mtime instead so records relying on mtime for TTL don't expire early. Self-heals if the file was removed externally (expiry cleanup). - Drop the per-write fsync: os.replace already guarantees readers never see a torn file, and cache data is re-fetchable — the flush bought nothing but card wear. API unchanged; DateTimeEncoder round-trip covered by tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FqzC1nzTWL4kaqgMaQZFam
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughDiskCache now serializes payloads once, tracks per-key Adler-32 digests, skips identical rewrites while refreshing mtimes, updates fallback writes, clears digest state, and adds tests for rewriting, recovery, compact JSON, and datetime persistence. ChangesDisk cache write economy
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant DiskCache
participant DateTimeEncoder
participant CacheFile
DiskCache->>DateTimeEncoder: serialize payload
DiskCache->>DiskCache: compute and compare Adler-32 digest
DiskCache->>CacheFile: refresh mtime or write payload
CacheFile-->>DiskCache: report write result
DiskCache->>DiskCache: record or clear digest state
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 0 |
| Duplication | 0 |
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
Summary
PR 1 of the performance/efficiency series (deep-dive findings).
DiskCache.setdidmkstemp → json.dump(indent=4) → flush+fsync → os.replace → chmodfor every key write on the persistent/var/cache/ledmatrix— with sports plugins in live mode that's dozens to 100+ force-flushed SD-card writes per minute, mostly rewriting byte-identical API data each update cycle. fsync-per-write is the classic SD-card killer.Changes (API unchanged):
indent=4(machine-read files; indenting just multiplied bytes written).os.utimeso records that rely on mtime for TTL don't expire early; self-heals if the file was removed externally.fsync:os.replacealready guarantees readers never see a torn file, and cache data is re-fetchable — the flush bought nothing but wear.Worst case of the per-process digest map: another process rewrites data redundantly — never a missed write.
Verification
mmcblk0diskstats): will post before/after deltas after deploy.🤖 Generated with Claude Code
https://claude.ai/code/session_01FqzC1nzTWL4kaqgMaQZFam
Summary by CodeRabbit