diff --git a/context/CONTEXT_2026-02-15.md b/context/CONTEXT_2026-02-15.md new file mode 100644 index 00000000..c3bac42d --- /dev/null +++ b/context/CONTEXT_2026-02-15.md @@ -0,0 +1 @@ +# Context - Perf Agent - 2026-02-15\nMission: Daily measurable improvement of app responsiveness. diff --git a/daily-perf-report-2026-02-15.md b/daily-perf-report-2026-02-15.md new file mode 100644 index 00000000..8e870e39 --- /dev/null +++ b/daily-perf-report-2026-02-15.md @@ -0,0 +1,30 @@ +# Daily Performance Report - 2026-02-15 + +## Summary +Executed daily performance audit. Identified and fixed a visibility gating issue in `ExploreDataService` to reduce background resource consumption. Verified documentation accuracy for uploads. + +## Findings & Fixes + +### P1: ExploreDataService Background Intervals +- **Issue**: `js/services/exploreDataService.js` was running `setInterval` loops for watch history (1m) and tag IDF (5m) updates even when the tab was hidden. +- **Impact**: Unnecessary CPU and battery usage for background tabs. +- **Fix**: Implemented `handleVisibility` to pause intervals when `document.hidden` is true and resume when visible. +- **Status**: **Fixed**. + +### P3: Other Background Tasks +- **`js/app/playbackCoordinator.js`**: Verified that torrent status updates are already visibility-gated. +- **`js/ui/ambientBackground.js`**: Verified that canvas animations are already visibility-gated. + +## Metrics +- **Performance Hits**: 198 (raw grep count). +- **Analyzed**: 3 specific services/controllers. +- **Artifacts**: `perf/hits-2026-02-15.json`. + +## Documentation Audit +- **Scope**: `content/docs/guides/upload-content.md` vs `js/ui/components/UploadModal.js`. +- **Result**: Documentation accurately reflects the supported file types, size recommendations (2GB limit due to client-side hashing), and upload methods (Direct R2/S3, External URL, Magnet). +- **Status**: **Aligned**. + +## Next Steps +- Monitor `ExploreDataService` for any regression in data freshness (though unlikely as it updates on visibility). +- Continue auditing other `setInterval` usages in future runs. diff --git a/decisions/DECISIONS_2026-02-15.md b/decisions/DECISIONS_2026-02-15.md new file mode 100644 index 00000000..adc8eb51 --- /dev/null +++ b/decisions/DECISIONS_2026-02-15.md @@ -0,0 +1,21 @@ +# Decision: Visibility Gating for ExploreDataService + +## Context +The `ExploreDataService` runs two `setInterval` loops (`watchHistoryInterval` and `tagIdfInterval`) to refresh data every 1 and 5 minutes, respectively. These loops spawn Web Workers to process data. + +## Problem +These intervals continue to run even when the browser tab is hidden or backgrounded, consuming CPU and battery unnecessarily. + +## Solution +Implement visibility gating: +- Listen for `visibilitychange` events on `document`. +- When `document.hidden` is true, clear the intervals. +- When `document.hidden` is false, restart the intervals. + +## Alternatives Considered +- Use `requestIdleCallback`: Still might run if the browser thinks it's idle but hidden. Visibility check is more direct for "user not looking". +- Increase interval when hidden: Still consumes some resources. Complete pause is better for this non-critical background task. + +## Verification +- Code review of `js/services/exploreDataService.js`. +- Lint check passed. diff --git a/docs/agents/task-logs/daily/2026-02-15_04-10-00_perf-agent_completed.md b/docs/agents/task-logs/daily/2026-02-15_04-10-00_perf-agent_completed.md new file mode 100644 index 00000000..12ff6036 --- /dev/null +++ b/docs/agents/task-logs/daily/2026-02-15_04-10-00_perf-agent_completed.md @@ -0,0 +1,28 @@ +# Daily Performance Agent Task - Completed + +**Agent:** perf-agent +**Date:** 2026-02-15 +**Status:** Completed + +## Summary +Executed daily performance audit. Identified and fixed a visibility gating issue in `ExploreDataService`. Verified documentation accuracy. + +## Actions Taken +1. **Context Initialization**: Created context files. +2. **Performance Scan**: Scanned codebase for performance patterns. +3. **Fix Implementation**: + - Modified `js/services/exploreDataService.js` to pause intervals when the tab is hidden. + - Added `handleVisibility` method bound to `visibilitychange` event. +4. **Docs Audit**: Verified `content/docs/guides/upload-content.md` matches implementation. +5. **Reporting**: Generated `daily-perf-report-2026-02-15.md` and `perf/hits-2026-02-15.json`. + +## Artifacts +- `js/services/exploreDataService.js` (Modified) +- `daily-perf-report-2026-02-15.md` +- `perf/hits-2026-02-15.json` +- `context/CONTEXT_2026-02-15.md` +- `decisions/DECISIONS_2026-02-15.md` + +## Verification +- Lint checks passed. +- Unit tests passed (via `node --test`). diff --git a/js/services/exploreDataService.js b/js/services/exploreDataService.js index 2f1def3d..27efcd44 100644 --- a/js/services/exploreDataService.js +++ b/js/services/exploreDataService.js @@ -143,15 +143,28 @@ export default class ExploreDataService { this.watchHistoryInterval = null; this.tagIdfInterval = null; this.unsubscribeHandlers = []; + this.handleVisibility = this.handleVisibility.bind(this); } initialize() { this.refreshWatchHistoryTagCounts({ force: true, reason: "init" }); this.refreshTagIdf({ force: true, reason: "init" }); this.subscribeToUpdates(); + if (typeof document !== "undefined") { + document.addEventListener("visibilitychange", this.handleVisibility); + } this.startIntervals(); } + handleVisibility() { + if (typeof document === "undefined") return; + if (document.hidden) { + this.clearIntervals(); + } else { + this.startIntervals(); + } + } + startIntervals() { this.clearIntervals(); if (Number.isFinite(this.historyRefreshIntervalMs) && this.historyRefreshIntervalMs > 0) { @@ -305,6 +318,9 @@ export default class ExploreDataService { destroy() { this.clearIntervals(); + if (typeof document !== "undefined") { + document.removeEventListener("visibilitychange", this.handleVisibility); + } if (this.watchHistoryRefreshHandle) { clearTimeout(this.watchHistoryRefreshHandle); diff --git a/perf/hits-2026-02-15.json b/perf/hits-2026-02-15.json new file mode 100644 index 00000000..7f13cc76 --- /dev/null +++ b/perf/hits-2026-02-15.json @@ -0,0 +1,29 @@ +[ + { + "file": "js/services/exploreDataService.js", + "line": 158, + "type": "setInterval", + "trigger": "initialization", + "impact": "Runs worker tasks every 1-5 minutes even when tab is hidden.", + "priority": "P1", + "fix": "Implement visibility gating." + }, + { + "file": "js/app/playbackCoordinator.js", + "line": 273, + "type": "setInterval", + "trigger": "torrent playback", + "impact": "Updates UI status", + "priority": "P3", + "note": "Already has visibility checks." + }, + { + "file": "js/ui/ambientBackground.js", + "line": 130, + "type": "requestAnimationFrame", + "trigger": "video playback", + "impact": "Canvas animation", + "priority": "P3", + "note": "Already has visibility checks." + } +]