Skip to content

perf: reduce timeline rendering and query work - #980

Draft
0xbrayo wants to merge 10 commits into
ActivityWatch:masterfrom
0xbrayo:perf/timeline-and-activity
Draft

perf: reduce timeline rendering and query work#980
0xbrayo wants to merge 10 commits into
ActivityWatch:masterfrom
0xbrayo:perf/timeline-and-activity

Conversation

@0xbrayo

@0xbrayo 0xbrayo commented Sep 11, 2026

Copy link
Copy Markdown
Member

This reduces work on large ActivityWatch datasets by reusing timeline event requests, caching category-history periods with invalidation, and rendering only timeline items near the visible viewport. It also reuses compiled category rules, destroys visualization resources on unmount, and replaces repeated graph/chart aggregation scans with map-based accumulators.

Validation: npm test (331 tests passed) and npm run build.

The branch contains six focused commits so each optimization can be reviewed independently.

@codecov

codecov Bot commented Sep 11, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.02956% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 60.12%. Comparing base (2ddc69f) to head (91bb428).
⚠️ Report is 5 commits behind head on master.

Files with missing lines Patch % Lines
src/stores/activity.ts 93.54% 3 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #980      +/-   ##
==========================================
+ Coverage   53.11%   60.12%   +7.01%     
==========================================
  Files          48       51       +3     
  Lines        2984     3105     +121     
  Branches      681      762      +81     
==========================================
+ Hits         1585     1867     +282     
+ Misses       1379     1171     -208     
- Partials       20       67      +47     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@greptile-apps

greptile-apps Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

The current PR appears safe to merge, with no outstanding correctness or security findings.

Summary

  • Reuses timeline event requests and renders only events near the visible timeline viewport.
  • Caches closed-period category-history queries with bounded expiry and write invalidation.
  • Keys retained category history by its generated query and periods so changed category rules or resolved buckets invalidate stale state.
  • Reuses compiled category rules and replaces repeated aggregation scans with map-based accumulators.
  • Cleans up timeline and force-graph resources when their components are destroyed.
  • Adds focused unit coverage for timeline indexing, caching, aggregation, request reuse, and cleanup behavior.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  View[Activity or Timeline view] --> Store[Activity and bucket stores]
  Store --> Client[ActivityWatch client]
  Client --> Server[ActivityWatch server]
  Store --> PeriodCache[Bounded category-period cache]
  Store --> EventIndex[Timeline event index]
  EventIndex --> Viewport[Viewport and buffer selection]
  Viewport --> DataSet[Incremental vis-data synchronization]
  DataSet --> Timeline[Rendered timeline]
  Client -->|successful writes| Invalidation[Shared cache invalidation]
  Invalidation --> PeriodCache
Loading

Reviews (5) · Last reviewed commit: "fix: key retained category history by th..."

Comment thread src/views/activity/Activity.vue
Comment thread src/util/timelineIndex.ts
The lint job fails CI with --max-warnings=0, tripped by no-shadow,
no-unused-vars, and vue/order-in-components warnings introduced by
the recent perf work.
@0xbrayo
0xbrayo force-pushed the perf/timeline-and-activity branch from a79ef7a to c7fd937 Compare September 11, 2026 05:09
@0xbrayo

0xbrayo commented Sep 11, 2026

Copy link
Copy Markdown
Member Author

🤖 Claude, on behalf of @0xbrayo

@greptile review

start_loading unconditionally cleared category.by_period even when
the current view doesn't request category history, which wiped out
data the Report view reads directly without loading it itself.
@0xbrayo

0xbrayo commented Sep 11, 2026

Copy link
Copy Markdown
Member Author

🤖 Claude, on behalf of @0xbrayo

@greptile review

Comment thread src/stores/activity.ts
Preserving category.by_period across views that skip reloading it
was safe only as long as the underlying host/timeperiod/filters
hadn't moved. Track the context the cache was computed for and clear
it whenever the new query no longer matches, so a view like Report
can't display category periods left over from a different context.
@0xbrayo

0xbrayo commented Sep 11, 2026

Copy link
Copy Markdown
Member Author

🤖 Claude, on behalf of @0xbrayo

@greptile review

Comment thread src/stores/activity.ts Outdated
Deciding whether a skipped category-history load can keep the cached
periods based on query options alone missed inputs that also shape the
result: the compiled category rules and the resolved bucket IDs. Reuse
the request that query_category_time_by_period already builds (query +
periods) as the identity of the current by_period, and make the keep or
clear decision in ensure_loaded once buckets are resolved, so a change
to categorization or bucket configuration invalidates it too.
@0xbrayo

0xbrayo commented Sep 11, 2026

Copy link
Copy Markdown
Member Author

🤖 Claude, on behalf of @0xbrayo

@greptile review

@0xbrayo
0xbrayo marked this pull request as draft September 11, 2026 09:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant