perf(traffic): optimize traffic data handling and improve performance

This commit is contained in:
Tunglies
2025-12-24 13:40:03 +08:00
parent 0992556b4a
commit 4ffb8b415f
11 changed files with 289 additions and 95 deletions
+8
View File
@@ -6,6 +6,7 @@ type SharedPollerEntry = {
timer: number | null;
interval: number;
callback: (() => void) | null;
lastFired: number;
refreshWhenHidden: boolean;
refreshWhenOffline: boolean;
};
@@ -32,6 +33,12 @@ const ensureTimer = (key: string, entry: SharedPollerEntry) => {
entry.timer = window.setInterval(() => {
if (!entry.refreshWhenHidden && isDocumentHidden()) return;
if (!entry.refreshWhenOffline && isOffline()) return;
const now = Date.now();
if (entry.lastFired && now - entry.lastFired < entry.interval / 2) {
// Skip duplicate fire within half interval to coalesce concurrent consumers
return;
}
entry.lastFired = now;
entry.callback?.();
}, entry.interval);
};
@@ -50,6 +57,7 @@ const registerSharedPoller = (
timer: null,
interval,
callback,
lastFired: 0,
refreshWhenHidden: options.refreshWhenHidden,
refreshWhenOffline: options.refreshWhenOffline,
};
+11 -1
View File
@@ -4,6 +4,7 @@ import useSWR from "swr";
import { getRunningMode, isAdmin, isServiceAvailable } from "@/services/cmds";
import { showNotice } from "@/services/notice-service";
import { useSharedSWRPoller } from "./use-shared-swr-poller";
import { useVerge } from "./use-verge";
export interface SystemState {
@@ -43,11 +44,20 @@ export function useSystemState() {
},
{
suspense: true,
refreshInterval: 30000,
refreshInterval: 0,
fallback: defaultSystemState,
},
);
useSharedSWRPoller(
"getSystemState",
30000,
() => {
void mutateSystemState();
},
{ refreshWhenHidden: false, refreshWhenOffline: false },
);
const isSidecarMode = systemState.runningMode === "Sidecar";
const isServiceMode = systemState.runningMode === "Service";
const isTunModeAvailable = systemState.isAdminMode || systemState.isServiceOk;
+4 -2
View File
@@ -5,10 +5,12 @@ import { useTrafficMonitorEnhanced } from "./use-traffic-monitor";
const FALLBACK_TRAFFIC: Traffic = { up: 0, down: 0 };
export const useTrafficData = () => {
export const useTrafficData = (options?: { enabled?: boolean }) => {
const enabled = options?.enabled ?? true;
const {
graphData: { appendData },
} = useTrafficMonitorEnhanced({ subscribe: false });
} = useTrafficMonitorEnhanced({ subscribe: false, enabled });
const { response, refresh } = useMihomoWsSubscription<ITrafficItem>({
storageKey: "mihomo_traffic_date",
buildSubscriptKey: (date) => `getClashTraffic-${date}`,
+27 -13
View File
@@ -343,8 +343,10 @@ const EMPTY_STATS: ISamplerStats = {
*/
export const useTrafficMonitorEnhanced = (options?: {
subscribe?: boolean;
enabled?: boolean;
}) => {
const subscribeToSnapshots = options?.subscribe ?? true;
const enabled = options?.enabled ?? true;
const [latestSnapshot, setLatestSnapshot] = useState<{
availableDataPoints: ITrafficDataPoint[];
samplerStats: ISamplerStats;
@@ -365,6 +367,8 @@ export const useTrafficMonitorEnhanced = (options?: {
// 注册引用计数与Worker生命周期
useEffect(() => {
if (!enabled) return;
const client = getWorkerClient();
clientRef.current = client;
@@ -396,43 +400,53 @@ export const useTrafficMonitorEnhanced = (options?: {
client.stop();
}
};
}, [subscribeToSnapshots]);
}, [enabled, subscribeToSnapshots]);
// Periodically refresh "now" so idle streams age out of the selected window when subscribed
useEffect(() => {
if (!subscribeToSnapshots) return;
if (!enabled || !subscribeToSnapshots) return;
const timer = window.setInterval(() => {
setNow(Date.now());
}, 1000);
return () => window.clearInterval(timer);
}, [subscribeToSnapshots]);
}, [enabled, subscribeToSnapshots]);
// 添加流量数据
const appendData = useCallback((traffic: Traffic) => {
clientRef.current?.appendData(traffic);
}, []);
const appendData = useCallback(
(traffic: Traffic) => {
if (!enabled) return;
clientRef.current?.appendData(traffic);
},
[enabled],
);
// 请求不同时间范围的数据
const requestRange = useCallback((minutes: number) => {
currentRangeRef.current = minutes;
setRangeMinutes(minutes);
clientRef.current?.setRange(minutes);
}, []);
const requestRange = useCallback(
(minutes: number) => {
if (!enabled) return;
currentRangeRef.current = minutes;
setRangeMinutes(minutes);
clientRef.current?.setRange(minutes);
},
[enabled],
);
// 清空数据
const clearData = useCallback(() => {
if (!enabled) return;
clientRef.current?.clearData();
}, []);
}, [enabled]);
const filteredDataPoints = useMemo(() => {
if (!enabled) return [];
const sourceData = latestSnapshot.availableDataPoints;
if (sourceData.length === 0) return [];
const cutoff = now - rangeMinutes * 60 * 1000;
return sourceData.filter((point) => point.timestamp > cutoff);
}, [latestSnapshot.availableDataPoints, rangeMinutes, now]);
}, [enabled, latestSnapshot.availableDataPoints, rangeMinutes, now]);
return {
graphData: {