Skip to content

[Repo Assist] perf: replace List.Insert(0) with LinkedList.AddFirst in NotificationHistoryService#143

Draft
github-actions[bot] wants to merge 1 commit intomasterfrom
repo-assist/perf-notificationhistory-linkedlist-2026-04-03-cffb89ca36854847
Draft

[Repo Assist] perf: replace List.Insert(0) with LinkedList.AddFirst in NotificationHistoryService#143
github-actions[bot] wants to merge 1 commit intomasterfrom
repo-assist/perf-notificationhistory-linkedlist-2026-04-03-cffb89ca36854847

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

@github-actions github-actions bot commented Apr 3, 2026

🤖 This PR was created by Repo Assist, an automated AI assistant.

Summary

NotificationHistoryService.AddNotification used List(T).Insert(0, ...) to prepend items, which is O(n) — the entire backing array must shift one position for every insertion. This is the same pattern fixed in ActivityStreamService in commit bd0a7b0 (PR #137).

Root Cause

// Before: O(n) per call
_history.Insert(0, new NotificationHistoryItem { ... });
while (_history.Count > MaxHistory)
    _history.RemoveAt(_history.Count - 1);

Both Insert(0, ...) and (for a full list) the trim loop together cost O(n) per notification. With a MaxHistory of 100, this is minor but unnecessary — and the pattern is easy to fix uniformly across the codebase.

Fix

Replace List(NotificationHistoryItem) with LinkedList(NotificationHistoryItem):

// After: O(1) per call
_history.AddFirst(new NotificationHistoryItem { ... });
while (_history.Count > MaxHistory)
    _history.RemoveLast();

AddFirst and RemoveLast are both O(1) on LinkedList(T). The GetHistory() snapshot via .ToList() (called on read, not write) is unchanged in complexity.

Trade-offs

  • LinkedList(T) has higher per-node overhead than List(T) (each node is an object). For a 100-item cap this is negligible (~6.4 KB total vs ~3.2 KB for a List).
  • GetHistory() still returns a List(T) snapshot, so callers are unaffected.

Test Status

Suite Result
OpenClaw.Shared.Tests ✅ All passed
OpenClaw.Tray.Tests ✅ All passed

No production logic was changed — only the collection type and its operation methods.

Generated by Repo Assist ·

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/repo-assist.md@cbb46ab386962aa371045839fc9998ee4e97ca64

…HistoryService

AddNotification previously called List<T>.Insert(0, ...) which is O(n)
due to array element shifting, followed by RemoveAt(_history.Count - 1)
to enforce MaxHistory. While RemoveAt on the last element is O(1), the
Insert(0) itself degrades to O(n) as history grows.

Mirrors the same fix applied to ActivityStreamService in commit bd0a7b0.

Change:
- List<NotificationHistoryItem> → LinkedList<NotificationHistoryItem>
- Insert(0, ...) → AddFirst(...)   [O(1)]
- RemoveAt(Count - 1) → RemoveLast()  [O(1)]
- GetHistory() ToList() snapshot is unaffected (IEnumerable<T> is sufficient)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants