Skip to content

Commit bac0e47

Browse files
committed
Merge branch 'perf/lhn-sort-cache' into perf/lhn-options-cache
2 parents e267744 + 9005d27 commit bac0e47

3 files changed

Lines changed: 28 additions & 3 deletions

File tree

src/libs/ReportActionsUtils.ts

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,8 @@ type SortedReportActionsCacheEntry = {
149149
lastAccessed: number;
150150
};
151151

152-
const SORTED_REPORT_ACTIONS_CACHE_MAX_SIZE = 1000;
152+
const DEFAULT_SORTED_REPORT_ACTIONS_CACHE_MAX_SIZE = 1000;
153+
let sortedReportActionsCacheMaxSize = DEFAULT_SORTED_REPORT_ACTIONS_CACHE_MAX_SIZE;
153154

154155
const sortedReportActionsCacheAscending = new Map<string, SortedReportActionsCacheEntry>();
155156
const sortedReportActionsCacheDescending = new Map<string, SortedReportActionsCacheEntry>();
@@ -643,14 +644,14 @@ function getCacheKeyForReportActions(reportActions: ReportAction[]): string {
643644
* Ensures cache doesn't exceed max size by removing least recently used entries (LRU).
644645
*/
645646
function evictOldestCacheEntries(cache: Map<string, SortedReportActionsCacheEntry>): void {
646-
if (cache.size <= SORTED_REPORT_ACTIONS_CACHE_MAX_SIZE) {
647+
if (cache.size <= sortedReportActionsCacheMaxSize) {
647648
return;
648649
}
649650

650651
const entries = Array.from(cache.entries());
651652
entries.sort((a, b) => a[1].lastAccessed - b[1].lastAccessed);
652653

653-
const entriesToRemove = cache.size - SORTED_REPORT_ACTIONS_CACHE_MAX_SIZE;
654+
const entriesToRemove = cache.size - sortedReportActionsCacheMaxSize;
654655
for (let i = 0; i < entriesToRemove; i++) {
655656
const entry = entries.at(i);
656657
if (entry !== undefined) {
@@ -659,6 +660,23 @@ function evictOldestCacheEntries(cache: Map<string, SortedReportActionsCacheEntr
659660
}
660661
}
661662

663+
/**
664+
* Adjust the maximum size for the sorted report actions cache.
665+
* Used by callers that know the current number of reports (e.g. LHN),
666+
* while still enforcing a global hard cap for safety.
667+
*/
668+
function setSortedReportActionsCacheMaxSize(newSize: number): void {
669+
if (!Number.isFinite(newSize) || newSize <= 0) {
670+
sortedReportActionsCacheMaxSize = DEFAULT_SORTED_REPORT_ACTIONS_CACHE_MAX_SIZE;
671+
} else {
672+
sortedReportActionsCacheMaxSize = newSize;
673+
}
674+
675+
// Immediately evict if current caches are above the new limit.
676+
evictOldestCacheEntries(sortedReportActionsCacheAscending);
677+
evictOldestCacheEntries(sortedReportActionsCacheDescending);
678+
}
679+
662680
/**
663681
* Sort an array of reportActions by their created timestamp first, and reportActionID second
664682
* This gives us a stable order even in the case of multiple reportActions created on the same millisecond
@@ -4030,6 +4048,7 @@ function hasReasoning(action: OnyxInputOrEntry<ReportAction>): boolean {
40304048
}
40314049

40324050
export {
4051+
setSortedReportActionsCacheMaxSize,
40334052
clearSortedReportActionsCache,
40344053
doesReportHaveVisibleActions,
40354054
extractLinksFromMessageHtml,

src/libs/SidebarUtils.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ import {
109109
isTagModificationAction,
110110
isTaskAction,
111111
isTransactionThread,
112+
setSortedReportActionsCacheMaxSize,
112113
} from './ReportActionsUtils';
113114
import type {OptionData} from './ReportUtils';
114115
import {
@@ -273,6 +274,10 @@ function getReportsToDisplayInLHN(
273274
) {
274275
const isInFocusMode = priorityMode === CONST.PRIORITY_MODE.GSD;
275276
const allReportsDictValues = reports ?? {};
277+
// Adjust the size of the sorted report actions cache to roughly match
278+
// the current number of reports, while still respecting the global cap
279+
// inside ReportActionsUtils to guard against excessive memory usage.
280+
setSortedReportActionsCacheMaxSize(Object.keys(allReportsDictValues).length);
276281
const reportsToDisplay: ReportsToDisplayInLHN = {};
277282

278283
for (const [reportID, report] of Object.entries(allReportsDictValues)) {

tests/unit/MiddlewareTest.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,7 @@ describe('Middleware', () => {
404404
}),
405405
}));
406406

407+
(global.fetch as jest.Mock).mockClear();
407408
SequentialQueue.unpause();
408409
await waitForBatchedUpdates();
409410

0 commit comments

Comments
 (0)