perf(stores): defer safeStorage writes off the interaction path (#1941)
* perf(stores): defer safeStorage writes off the interaction path Session switches funnel every persisted store slice through safeStorage.setItem, and doing those large JSON.stringify writes synchronously blocked the main thread for over a second. Add a write-behind buffer that: - Defers each setItem/removeItem to a later task via setTimeout(0) so the click-to-paint path is not blocked. - Coalesces repeated writes to the same key into a single backing flush. - Serves pending values from memory so read-after-write stays consistent within the deferral window. - Flushes synchronously on pagehide/beforeunload/visibilitychange/freeze so deferred state survives tab close, reload, and the mobile freeze lifecycle. Adds a test covering write deferral, coalescing, and pending read serving. * fix(stores): defer persisted JSON serialization * fix(stores): defer direct safeStorage writes --------- Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
This commit is contained in:
committed by
GitHub
co-authored by
Bohdan Triapitsyn
parent
088a70fe5a
commit
1505274f94
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { getSafeStorage } from '@/stores/utils/safeStorage';
|
||||
import { getDeferredSafeStorage } from '@/stores/utils/safeStorage';
|
||||
import { updateDesktopSettings } from '@/lib/persistence';
|
||||
|
||||
const SHOW_HIDDEN_STORAGE_KEY = 'directoryTreeShowHidden';
|
||||
@@ -10,7 +10,7 @@ const readStoredShowHidden = (): boolean => {
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
const stored = getSafeStorage().getItem(SHOW_HIDDEN_STORAGE_KEY);
|
||||
const stored = getDeferredSafeStorage().getItem(SHOW_HIDDEN_STORAGE_KEY);
|
||||
if (stored === null) {
|
||||
return true;
|
||||
}
|
||||
@@ -35,7 +35,7 @@ export const setDirectoryShowHidden = (
|
||||
return;
|
||||
}
|
||||
try {
|
||||
getSafeStorage().setItem(SHOW_HIDDEN_STORAGE_KEY, value ? 'true' : 'false');
|
||||
getDeferredSafeStorage().setItem(SHOW_HIDDEN_STORAGE_KEY, value ? 'true' : 'false');
|
||||
notifyDirectoryShowHiddenChanged();
|
||||
} catch {
|
||||
// ignore storage errors
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
|
||||
import { getSafeStorage } from '@/stores/utils/safeStorage';
|
||||
import { getDeferredSafeStorage } from '@/stores/utils/safeStorage';
|
||||
import { updateDesktopSettings } from '@/lib/persistence';
|
||||
|
||||
const SHOW_GITIGNORED_STORAGE_KEY = 'filesViewShowGitignored';
|
||||
@@ -11,7 +11,7 @@ const readStoredShowGitignored = (): boolean => {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
const stored = getSafeStorage().getItem(SHOW_GITIGNORED_STORAGE_KEY);
|
||||
const stored = getDeferredSafeStorage().getItem(SHOW_GITIGNORED_STORAGE_KEY);
|
||||
return stored === 'true';
|
||||
} catch {
|
||||
return false;
|
||||
@@ -33,7 +33,7 @@ export const setFilesViewShowGitignored = (
|
||||
return;
|
||||
}
|
||||
try {
|
||||
getSafeStorage().setItem(SHOW_GITIGNORED_STORAGE_KEY, value ? 'true' : 'false');
|
||||
getDeferredSafeStorage().setItem(SHOW_GITIGNORED_STORAGE_KEY, value ? 'true' : 'false');
|
||||
notifyFilesViewShowGitignoredChanged();
|
||||
} catch {
|
||||
// ignore storage errors
|
||||
|
||||
Reference in New Issue
Block a user