Merge pull request #2534 from PR0M3TH3AN/agents/daily/perf-agent-4875619209506006964

perf: visibility gating for LoginModalController
This commit is contained in:
thePR0M3TH3AN authored and GitHub committed 2026-02-15 11:07:30 -05:00
commit fc414e35ff
8 files changed
+155 -42

No files matched your search

+18 -1
View File
@@ -1 +1,18 @@
# Context - Perf Agent - 2026-02-15\nMission: Daily measurable improvement of app responsiveness.
# Context
**Goal**: Daily measurable improvement of app responsiveness and documentation alignment.
**Scope**:
- Identify performance bottlenecks (CPU/network).
- Apply small, safe fixes (visibility gating, bounded concurrency).
- Audit and update `/content` documentation.
**Assumptions**:
- `unstable` branch is the target.
- Tests must pass.
- Changes must be documented.
**Definition of Done**:
- `perf/hits-YYYY-MM-DD.json` created.
- `perf/daily-perf-report-YYYY-MM-DD.md` created.
- At least one small fix or docs update (if applicable).
+4 -20
View File
@@ -1,21 +1,5 @@
# Decision: Visibility Gating for ExploreDataService
# Decisions
## 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.
- Using `grep` to find performance patterns.
- Focusing on `js/ui/loginModalController.js` for visibility gating as suggested by memory.
- Will verify `/content` docs against code.
@@ -0,0 +1,31 @@
# Daily Performance Report: 2026-02-15
**Summary**: Visibility gating implemented for `LoginModalController` to reduce background CPU usage. Upload documentation verified.
## Findings
### P2: Background CPU Usage
* **File**: `js/ui/loginModalController.js`
* **Issue**: Uses `setInterval` (500ms) for modal close polling (fallback for MutationObserver) which runs even when the tab is hidden.
* **Fix**: Implemented `handleVisibility` to clear the interval when `document.hidden` is true, and restart it when visible.
* **Status**: Fixed.
### Verified Existing Mitigations
* `js/services/exploreDataService.js`: Already uses `handleVisibility` to gate `watchHistoryInterval` and `tagIdfInterval`.
* `js/app/playbackCoordinator.js`: Already uses `document.visibilityState` check and visibility handlers for `torrentStatusIntervalId`.
### P2: Upload Performance
* **File**: `js/storage/s3-multipart.js`
* **Observation**: Uses 5MB minimum part size for S3 multipart uploads. Correctly continues upload in background (doesn't pause on hidden), which is desired for user uploads.
* **Docs**: Verified `/content/docs/guides/upload-content.md` aligns with code (multipart upload, client-side hashing memory note).
## Metrics
* **Login Time**: Not measured in this run.
* **Queue Sizes**: Not measured.
## Actions
* **Code Change**: Updated `js/ui/loginModalController.js` to add visibility gating.
* **Documentation**: Confirmed alignment of upload docs.
## Blockers
* None.
+25
View File
@@ -294,6 +294,7 @@ export default class LoginModalController {
this.modalCloseIntervalId = null;
this.isSelectionInProgress = false;
this.nip46AutoStartTimer = null;
this.handleVisibility = this.handleVisibility.bind(this);
this.initializeRemoteSignerStatus();
this.initialized = false;
@@ -320,6 +321,10 @@ export default class LoginModalController {
// Start tracking modal close events to reset per-session key generation state.
this.initializeModalCloseTracking();
if (typeof document !== "undefined") {
document.addEventListener("visibilitychange", this.handleVisibility);
}
if (typeof this.lastRemoteSignerStatus !== "undefined") {
this.applyRemoteSignerStatus(this.lastRemoteSignerStatus);
}
@@ -328,6 +333,22 @@ export default class LoginModalController {
this.initialized = true;
}
handleVisibility() {
if (typeof document === "undefined") return;
if (document.hidden) {
if (
this.modalCloseIntervalId &&
this.window &&
typeof this.window.clearInterval === "function"
) {
this.window.clearInterval(this.modalCloseIntervalId);
this.modalCloseIntervalId = null;
}
} else {
this.initializeModalCloseTracking();
}
}
initializeModalCloseTracking() {
const modal = this.modalElement;
if (!(modal instanceof HTMLElement)) {
@@ -2487,6 +2508,10 @@ export default class LoginModalController {
}
destroy() {
if (typeof document !== "undefined") {
document.removeEventListener("visibilitychange", this.handleVisibility);
}
if (this.modalCloseObserver) {
try {
this.modalCloseObserver.disconnect();
+31
View File
@@ -0,0 +1,31 @@
# Daily Performance Report: 2026-02-15
**Summary**: Visibility gating implemented for `LoginModalController` to reduce background CPU usage. Upload documentation verified.
## Findings
### P2: Background CPU Usage
* **File**: `js/ui/loginModalController.js`
* **Issue**: Uses `setInterval` (500ms) for modal close polling (fallback for MutationObserver) which runs even when the tab is hidden.
* **Fix**: Implemented `handleVisibility` to clear the interval when `document.hidden` is true, and restart it when visible.
* **Status**: Fixed.
### Verified Existing Mitigations
* `js/services/exploreDataService.js`: Already uses `handleVisibility` to gate `watchHistoryInterval` and `tagIdfInterval`.
* `js/app/playbackCoordinator.js`: Already uses `document.visibilityState` check and visibility handlers for `torrentStatusIntervalId`.
### P2: Upload Performance
* **File**: `js/storage/s3-multipart.js`
* **Observation**: Uses 5MB minimum part size for S3 multipart uploads. Correctly continues upload in background (doesn't pause on hidden), which is desired for user uploads.
* **Docs**: Verified `/content/docs/guides/upload-content.md` aligns with code (multipart upload, client-side hashing memory note).
## Metrics
* **Login Time**: Not measured in this run.
* **Queue Sizes**: Not measured.
## Actions
* **Code Change**: Updated `js/ui/loginModalController.js` to add visibility gating.
* **Documentation**: Confirmed alignment of upload docs.
## Blockers
* None.
+29 -21
View File
@@ -1,29 +1,37 @@
[
{
"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/ui/loginModalController.js",
"pattern": "setInterval",
"line": "initializeModalCloseTracking",
"trigger": "always (fallback)",
"impact": "Main thread polling (500ms) when MutationObserver missing. Should be gated."
},
{
"file": "js/ui/loginModalController.js",
"pattern": "setInterval",
"line": "startModalCloseWatch",
"trigger": "login flow (fallback)",
"impact": "Main thread polling (200ms) during login. Should be gated."
},
{
"file": "js/viewCounter.js",
"pattern": "setTimeout",
"line": "persistTimer",
"trigger": "view count update",
"impact": "Debounced local storage write. Low impact."
},
{
"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",
"pattern": "setInterval",
"line": "startTorrentStatusInterval",
"trigger": "video playback",
"impact": "Canvas animation",
"priority": "P3",
"note": "Already has visibility checks."
"impact": "Torrent status polling (3000ms). Already visibility gated."
},
{
"file": "js/services/exploreDataService.js",
"pattern": "setInterval",
"line": "startIntervals",
"trigger": "background data refresh",
"impact": "IDF/History refresh. Already visibility gated."
}
]
+10
View File
@@ -0,0 +1,10 @@
# Test Log
**Environment**:
- Node.js: v22.22.0
- Branch: unstable
**Commands**:
- `npm ci`
- `npm run lint`
- `npm run test:unit` (shard)
+7
View File
@@ -0,0 +1,7 @@
# TODO
- [ ] Run search patterns and generate `perf/hits-2026-02-15.json`.
- [ ] Analyze hits and prioritize.
- [ ] Implement small safe fix (e.g., visibility gating in `js/ui/loginModalController.js` or `js/services/exploreDataService.js`).
- [ ] Audit `/content` documentation.
- [ ] Generate `perf/daily-perf-report-2026-02-15.md`.