mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-12 12:06:16 -08:00
perf(workspace): share the startup inventory read and defer non-first-card IPC (J1)
Journey J1 / renderer.ipcCallsToFirstCard: 12 -> 7. - PlaylistsService.getAllPlaylists() shares one in-flight SQLite read between concurrent callers (the playlist effect and the XMLTV source reconciliation at startup). Settled reads are never reused and every SQLite write detaches the pending read. - getM3uFavoriteChannels() stops re-reading the write-once IndexedDB -> SQLite migration receipt once it has been seen. - StartupDeferralService holds the download list, app update status and the dashboard's recent items and favorites until one task after the render that reveals the routed content (5 s safety timeout). IPTVNATOR_DISABLE_STARTUP_DEFERRAL=1 is the kill switch. - reconcileEpgSources and the two distinct migration-flag reads stay on the critical path: the first is the #1548 revision fence, the second are different keys, not duplicates. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
76dd8c099e
commit
e5ee064407
24 files changed
+648
-23
No files matched your search
@@ -179,6 +179,35 @@ harness, which is what the ratchet needs. The main process start
|
||||
(`Date.now() - process.uptime()`) is recorded per iteration under
|
||||
`evidence.epochs` for cross-checks.
|
||||
|
||||
### Startup work before the first card
|
||||
|
||||
`renderer.ipcCallsToFirstCard` counts what the renderer asks of the main
|
||||
process before the first card. Only work that the first card needs may run
|
||||
before it:
|
||||
|
||||
- `PlaylistsService.getAllPlaylists()` shares one in-flight SQLite read
|
||||
between concurrent callers (`SharedInFlightRead`): at startup the playlist
|
||||
effect and the XMLTV source reconciliation both read the inventory, and the
|
||||
second caller joins the first read and receives a copy. A settled read is
|
||||
never reused, and every SQLite write detaches the pending read, so a caller
|
||||
that follows a write reads again.
|
||||
- `StartupDeferralService` (`@iptvnator/services`) holds work the first
|
||||
screen does not need: the initial download list (the header badge), the
|
||||
app update status (the update card), and the dashboard's recent items and
|
||||
favorites. `app.config.ts` arms it with `STARTUP_WORK_DEFERRAL`, and
|
||||
`AppStartupStatusComponent` opens it one task after the render that
|
||||
reveals the routed content, so released work never lands in the task of
|
||||
the first card. It opens on its own after 5 s if that render never
|
||||
happens. Without the token (tests, other hosts) the gate is open.
|
||||
- `IPTVNATOR_DISABLE_STARTUP_DEFERRAL=1` (or `true`) is the short-lived kill
|
||||
switch: the preload exposes it as `startupDeferralDisabled` and the gate
|
||||
starts open. Remove it within two releases of the change that added it.
|
||||
- `reconcileEpgSources` stays before the first card on purpose: its
|
||||
completion bumps `EpgSourceSettingsService.revision()`, the fence that
|
||||
keeps XMLTV lookups from returning data of a removed source. Deferring it
|
||||
would let dashboard EPG lookups start first and then be discarded and
|
||||
requeued.
|
||||
|
||||
### Summary schema
|
||||
|
||||
```json
|
||||
|
||||
@@ -282,7 +282,11 @@ hooks: `dashboard-hero`, `dashboard-hero-slide` (`data-hero-kind`),
|
||||
`updateDate` / `importDate` for sources that have never been used.
|
||||
3. `DashboardDataService` is passive on construction. The dashboard feature
|
||||
owns the initial reloads for recent items, favorites, and Xtream recently
|
||||
added rows on page entry.
|
||||
added rows on page entry. Recent items and favorites reload through
|
||||
`reloadForPageEntry()`, which on launch waits for `StartupDeferralService`
|
||||
(the first rendered screen, journey J1); their rails keep their scoped
|
||||
skeletons meanwhile, and the Xtream recently-added and TMDB rails follow
|
||||
`globalFavoritesLoaded()` as before. Later page entries find the gate open.
|
||||
4. No dashboard-local `Layout` state, no localStorage keys, no migrations.
|
||||
Per-rail visibility is the one persisted preference, and it lives in the
|
||||
global settings store (`Settings.dashboardRails`), not in a
|
||||
|
||||
@@ -34,6 +34,7 @@ IPTVNATOR_TRACE_STARTUP=1 pnpm nx serve electron-backend
|
||||
- `IPTVNATOR_PERF_COUNT_SQL=1`, together with `IPTVNATOR_PERF_CAPTURE=1`, also counts every SQL statement of the main-process and database-worker connections for `main.sqlStatementsBeforeReadyToShow`; it wraps each statement execution, including every row of a bulk insert, so only the launch journey sets it and the import benchmarks leave it unset
|
||||
- `IPTVNATOR_PERF_WORKER_PROFILING=1` enables development/test-only, request-scoped worker receive/work/response-post timestamps, thread CPU, event-loop utilization/delay, count-only playlist serialization/SQLite write/read/deserialization plus Xtream category/content/cache-clear/delete/in-source-search phase events, profiling-only worker cancel-receipt acknowledgements, valid-sample-counted isolate peak memory, and the database worker's idle-only one-shot post-GC heap probe; overlapping database requests are explicitly invalidated instead of misattributed, the performance benchmark sets the flag automatically, and production launches must leave it unset
|
||||
- `IPTVNATOR_DISABLE_COMPILE_CACHE=1` disables the main-process V8 compile cache; `IPTVNATOR_COMPILE_CACHE_DIR=<dir>` relocates it. The startup trace reports the outcome as `compile-cache`
|
||||
- `IPTVNATOR_DISABLE_STARTUP_DEFERRAL=1` starts the renderer's startup gate open, so the download list, update status and dashboard recent/favorites reads run before the first screen again (kill switch; see "Startup work before the first card" in `docs/architecture/performance-journeys.md`)
|
||||
|
||||
- Settings, portal request/response, and trace payloads must use
|
||||
`@iptvnator/shared/logging` or the redacting portal logger before reaching
|
||||
|
||||
Reference in new issue
Block a user