Skip to content

Commit 17d3164

Browse files
committed
perf: 动态监控按时切断 MutationObserver
callback 早退只省 JS 时间,浏览器层面仍以约 1500 records/s 持续派发 mutation 跨 isolated world,是真正吃主线程的部分。改为冷却期直接 disconnect observer、5 秒后再 observe;启动 30 秒后强制 disconnect 后续靠 PerformanceObserver 抓资源;监听目标缩到 body 去掉 head 子树噪音;SPA 路由切换时补一次 body 扫描补 markers。将版本号提升到 1.2.82。
1 parent c52bba4 commit 17d3164

2 files changed

Lines changed: 51 additions & 3 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "stackprism",
33
"private": true,
4-
"version": "1.2.81",
4+
"version": "1.2.82",
55
"type": "module",
66
"description": "StackPrism 用于检测网页前端、后端、CDN、SaaS、广告营销、统计、登录、支付、网站程序和主题模板线索。",
77
"scripts": {

src/content/content-observer.ts

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
const MUTATION_BURST_THRESHOLD = 150
1111
const MUTATION_COOLDOWN_MS = 5000
1212
const MUTATION_FLUSH_DELAY = 200
13+
const MUTATION_OBSERVER_LIFETIME_MS = 30000
1314
const CONTEXT_INVALIDATED_PATTERN = /extension context invalidated|context invalidated/i
1415
const OBSERVER_INSTANCE_KEY = '__stackPrismContentObserver__'
1516
const SKIP_TAGS = new Set(['VIDEO', 'AUDIO', 'CANVAS', 'PICTURE', 'SOURCE', 'TRACK', 'SVG', 'IMG'])
@@ -51,6 +52,8 @@
5152
let mutationBurstWindowStart = Date.now()
5253
let mutationBurstCount = 0
5354
let mutationCooldownUntil = 0
55+
let mutationCooldownReconnect = 0
56+
let mutationLifetimeTimer = 0
5457

5558
// ----- 调试埋点(默认关闭,开启:localStorage.setItem('__sp_observer_debug__','1') + 刷新) -----
5659

@@ -380,6 +383,11 @@
380383
state.url = location.href
381384
state.title = document.title
382385
collectStaticSnapshot()
386+
try {
387+
if (document.body) collectFromElement(document.body)
388+
} catch {
389+
// ignore
390+
}
383391
addDomMarker(`route:${location.pathname}${location.search}`)
384392
scheduleSend()
385393
}
@@ -411,6 +419,14 @@
411419
pendingMutationFrame = 0
412420
}
413421
pendingMutationNodes = []
422+
if (mutationCooldownReconnect) {
423+
window.clearTimeout(mutationCooldownReconnect)
424+
mutationCooldownReconnect = 0
425+
}
426+
if (mutationLifetimeTimer) {
427+
window.clearTimeout(mutationLifetimeTimer)
428+
mutationLifetimeTimer = 0
429+
}
414430
if (perfDumpTimer) {
415431
window.clearInterval(perfDumpTimer)
416432
perfDumpTimer = 0
@@ -518,17 +534,37 @@
518534
pendingMutationFrame = setTimeout(processPendingMutationNodes, MUTATION_FLUSH_DELAY)
519535
}
520536

537+
const observeMutationTarget = () => {
538+
if (!mutationObserver) return
539+
const target = document.body || document.documentElement || document
540+
try {
541+
mutationObserver.observe(target, { childList: true, subtree: true })
542+
} catch {
543+
// ignore
544+
}
545+
}
546+
521547
const triggerMutationCooldown = now => {
522548
mutationCooldownUntil = now + MUTATION_COOLDOWN_MS
523549
pendingMutationNodes = []
524550
if (pendingMutationFrame) {
525551
clearTimeout(pendingMutationFrame)
526552
pendingMutationFrame = 0
527553
}
554+
if (mutationObserver) {
555+
mutationObserver.disconnect()
556+
if (mutationCooldownReconnect) {
557+
window.clearTimeout(mutationCooldownReconnect)
558+
}
559+
mutationCooldownReconnect = window.setTimeout(() => {
560+
mutationCooldownReconnect = 0
561+
if (stopped) return
562+
observeMutationTarget()
563+
}, MUTATION_COOLDOWN_MS)
564+
}
528565
}
529566

530567
const installMutationObserver = () => {
531-
const root = document.documentElement || document
532568
const observer = new MutationObserver(mutations => {
533569
if (stopped) return
534570
const now = Date.now()
@@ -573,7 +609,7 @@
573609
perfMeasure('sp:mutation-callback', 'sp:mo-start', { mutations: mutations.length, accepted, cooldown: false })
574610
})
575611
mutationObserver = observer
576-
observer.observe(root, { childList: true, subtree: true })
612+
observeMutationTarget()
577613
}
578614

579615
const installNavigationObserver = () => {
@@ -618,6 +654,18 @@
618654
installMutationObserver()
619655
installNavigationObserver()
620656
scheduleSend()
657+
mutationLifetimeTimer = window.setTimeout(() => {
658+
mutationLifetimeTimer = 0
659+
if (stopped) return
660+
if (mutationCooldownReconnect) {
661+
window.clearTimeout(mutationCooldownReconnect)
662+
mutationCooldownReconnect = 0
663+
}
664+
if (mutationObserver) {
665+
mutationObserver.disconnect()
666+
mutationObserver = null
667+
}
668+
}, MUTATION_OBSERVER_LIFETIME_MS)
621669
if (PERF_DEBUG) {
622670
console.log('[StackPrism observer] 性能埋点已启用,每 ' + PERF_DUMP_INTERVAL_MS + 'ms 输出一次摘要')
623671
perfDumpTimer = window.setInterval(dumpPerfSnapshot, PERF_DUMP_INTERVAL_MS)

0 commit comments

Comments
 (0)