mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-11-05 07:02:09 +08:00
perf: reduce traffic update allocations
This commit is contained in:
@@ -20,6 +20,8 @@ export interface TrafficRef {
|
||||
toggleStyle: () => void
|
||||
}
|
||||
|
||||
type TrafficValueKey = 'up' | 'down'
|
||||
|
||||
/**
|
||||
* draw the traffic graph
|
||||
*/
|
||||
@@ -101,42 +103,49 @@ export function TrafficGraph({ ref }: { ref?: Ref<TrafficRef> }) {
|
||||
return 1
|
||||
}
|
||||
|
||||
const drawBezier = (list: number[], offset: number) => {
|
||||
const points = list.map((y, i) => [
|
||||
(dx * (i - 1) - offset + 3) | 0,
|
||||
countY(y),
|
||||
])
|
||||
const drawBezier = (
|
||||
list: Traffic[],
|
||||
valueKey: TrafficValueKey,
|
||||
offset: number,
|
||||
) => {
|
||||
if (list.length === 0) return
|
||||
|
||||
context.moveTo(points[0][0], points[0][1])
|
||||
const firstX = (dx * -1 - offset + 3) | 0
|
||||
const firstY = countY(list[0]?.[valueKey] ?? 0)
|
||||
|
||||
for (let i = 1; i < points.length; i++) {
|
||||
const p1 = points[i]
|
||||
const p2 = points[i + 1] || p1
|
||||
context.moveTo(firstX, firstY)
|
||||
|
||||
const x1 = (p1[0] + p2[0]) / 2
|
||||
const y1 = (p1[1] + p2[1]) / 2
|
||||
for (let i = 1; i < list.length; i++) {
|
||||
const p1x = (dx * (i - 1) - offset + 3) | 0
|
||||
const p1y = countY(list[i]?.[valueKey] ?? 0)
|
||||
|
||||
context.quadraticCurveTo(p1[0], p1[1], x1, y1)
|
||||
const hasNext = i + 1 < list.length
|
||||
const p2x = hasNext ? (dx * i - offset + 3) | 0 : p1x
|
||||
const p2y = hasNext ? countY(list[i + 1]?.[valueKey] ?? 0) : p1y
|
||||
|
||||
context.quadraticCurveTo(p1x, p1y, (p1x + p2x) / 2, (p1y + p2y) / 2)
|
||||
}
|
||||
}
|
||||
|
||||
const drawLine = (list: number[], offset: number) => {
|
||||
const points = list.map((y, i) => [
|
||||
(dx * (i - 1) - offset) | 0,
|
||||
countY(y),
|
||||
])
|
||||
const drawLine = (
|
||||
list: Traffic[],
|
||||
valueKey: TrafficValueKey,
|
||||
offset: number,
|
||||
) => {
|
||||
if (list.length === 0) return
|
||||
|
||||
context.moveTo(points[0][0], points[0][1])
|
||||
context.moveTo((dx * -1 - offset) | 0, countY(list[0]?.[valueKey] ?? 0))
|
||||
|
||||
for (let i = 1; i < points.length; i++) {
|
||||
const p = points[i]
|
||||
context.lineTo(p[0], p[1])
|
||||
for (let i = 1; i < list.length; i++) {
|
||||
context.lineTo(
|
||||
(dx * (i - 1) - offset) | 0,
|
||||
countY(list[i]?.[valueKey] ?? 0),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const drawGraph = (lastTime: number) => {
|
||||
const listUp = listRef.current.map((v) => v.up)
|
||||
const listDown = listRef.current.map((v) => v.down)
|
||||
const list = listRef.current
|
||||
const lineStyle = styleRef.current
|
||||
|
||||
const now = Date.now()
|
||||
@@ -168,9 +177,9 @@ export function TrafficGraph({ ref }: { ref?: Ref<TrafficRef> }) {
|
||||
context.lineWidth = upLineWidth
|
||||
context.strokeStyle = upLineColor
|
||||
if (lineStyle) {
|
||||
drawBezier(listUp, offset)
|
||||
drawBezier(list, 'up', offset)
|
||||
} else {
|
||||
drawLine(listUp, offset)
|
||||
drawLine(list, 'up', offset)
|
||||
}
|
||||
context.stroke()
|
||||
context.closePath()
|
||||
@@ -180,9 +189,9 @@ export function TrafficGraph({ ref }: { ref?: Ref<TrafficRef> }) {
|
||||
context.lineWidth = downLineWidth
|
||||
context.strokeStyle = downLineColor
|
||||
if (lineStyle) {
|
||||
drawBezier(listDown, offset)
|
||||
drawBezier(list, 'down', offset)
|
||||
} else {
|
||||
drawLine(listDown, offset)
|
||||
drawLine(list, 'down', offset)
|
||||
}
|
||||
context.stroke()
|
||||
context.closePath()
|
||||
|
||||
@@ -8,6 +8,26 @@ export interface IMemoryUsageItem {
|
||||
}
|
||||
|
||||
const FALLBACK_MEMORY_USAGE: IMemoryUsageItem = { inuse: 0 }
|
||||
const DUPLICATE_MEMORY_WINDOW_MS = 50
|
||||
|
||||
let lastMemorySignature = ''
|
||||
let lastMemoryTimestamp = 0
|
||||
|
||||
const shouldSkipDuplicateMemory = (memory: IMemoryUsageItem) => {
|
||||
const now = Date.now()
|
||||
const signature = `${memory.inuse}:${memory.oslimit ?? ''}`
|
||||
|
||||
if (
|
||||
signature === lastMemorySignature &&
|
||||
now - lastMemoryTimestamp <= DUPLICATE_MEMORY_WINDOW_MS
|
||||
) {
|
||||
return true
|
||||
}
|
||||
|
||||
lastMemorySignature = signature
|
||||
lastMemoryTimestamp = now
|
||||
return false
|
||||
}
|
||||
|
||||
export const useMemoryData = () => {
|
||||
const { response, refresh } = useMihomoWsSubscription<IMemoryUsageItem>({
|
||||
@@ -26,6 +46,9 @@ export const useMemoryData = () => {
|
||||
|
||||
try {
|
||||
const parsed = JSON.parse(data) as IMemoryUsageItem
|
||||
if (shouldSkipDuplicateMemory(parsed)) {
|
||||
return
|
||||
}
|
||||
next(null, parsed)
|
||||
} catch (error) {
|
||||
next(error, FALLBACK_MEMORY_USAGE)
|
||||
|
||||
@@ -4,6 +4,26 @@ import { useMihomoWsSubscription } from './use-mihomo-ws-subscription'
|
||||
import { useTrafficMonitorEnhanced } from './use-traffic-monitor'
|
||||
|
||||
const FALLBACK_TRAFFIC: Traffic = { up: 0, down: 0 }
|
||||
const DUPLICATE_TRAFFIC_WINDOW_MS = 50
|
||||
|
||||
let lastTrafficSignature = ''
|
||||
let lastTrafficTimestamp = 0
|
||||
|
||||
const shouldSkipDuplicateTraffic = (traffic: Traffic) => {
|
||||
const now = Date.now()
|
||||
const signature = `${traffic.up}:${traffic.down}`
|
||||
|
||||
if (
|
||||
signature === lastTrafficSignature &&
|
||||
now - lastTrafficTimestamp <= DUPLICATE_TRAFFIC_WINDOW_MS
|
||||
) {
|
||||
return true
|
||||
}
|
||||
|
||||
lastTrafficSignature = signature
|
||||
lastTrafficTimestamp = now
|
||||
return false
|
||||
}
|
||||
|
||||
export const useTrafficData = (options?: { enabled?: boolean }) => {
|
||||
const enabled = options?.enabled ?? true
|
||||
@@ -27,6 +47,9 @@ export const useTrafficData = (options?: { enabled?: boolean }) => {
|
||||
|
||||
try {
|
||||
const parsed = JSON.parse(data) as Traffic
|
||||
if (shouldSkipDuplicateTraffic(parsed)) {
|
||||
return
|
||||
}
|
||||
appendData(parsed)
|
||||
next(null, parsed)
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user