@gracker/smartperfetto 1.0.15 → 1.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/agents/base/baseAgent.d.ts.map +1 -1
- package/dist/agent/agents/base/baseAgent.js +5 -1
- package/dist/agent/agents/base/baseAgent.js.map +1 -1
- package/dist/agent/context/enhancedSessionContext.d.ts +5 -0
- package/dist/agent/context/enhancedSessionContext.d.ts.map +1 -1
- package/dist/agent/context/enhancedSessionContext.js +13 -0
- package/dist/agent/context/enhancedSessionContext.js.map +1 -1
- package/dist/agent/core/conclusionContract.d.ts +23 -1
- package/dist/agent/core/conclusionContract.d.ts.map +1 -1
- package/dist/agent/core/conclusionGenerator.d.ts.map +1 -1
- package/dist/agent/core/conclusionGenerator.js +223 -27
- package/dist/agent/core/conclusionGenerator.js.map +1 -1
- package/dist/agent/core/executors/directSkillExecutor.d.ts.map +1 -1
- package/dist/agent/core/executors/directSkillExecutor.js +6 -12
- package/dist/agent/core/executors/directSkillExecutor.js.map +1 -1
- package/dist/agent/core/orchestratorTypes.d.ts +6 -0
- package/dist/agent/core/orchestratorTypes.d.ts.map +1 -1
- package/dist/agent/core/orchestratorTypes.js.map +1 -1
- package/dist/agent/experts/crossDomain/moduleExpertInvoker.d.ts.map +1 -1
- package/dist/agent/experts/crossDomain/moduleExpertInvoker.js +4 -1
- package/dist/agent/experts/crossDomain/moduleExpertInvoker.js.map +1 -1
- package/dist/agent/scene/sceneStage1Runner.d.ts +1 -1
- package/dist/agent/scene/sceneStage1Runner.d.ts.map +1 -1
- package/dist/agent/scene/sceneStage1Runner.js +1 -1
- package/dist/agent/scene/sceneStage1Runner.js.map +1 -1
- package/dist/agent/scene/sceneStoryService.d.ts +1 -1
- package/dist/agent/scene/sceneStoryService.d.ts.map +1 -1
- package/dist/agent/scene/sceneStoryService.js +4 -1
- package/dist/agent/scene/sceneStoryService.js.map +1 -1
- package/dist/agent/types/agentProtocol.d.ts.map +1 -1
- package/dist/agent/types/agentProtocol.js +4 -1
- package/dist/agent/types/agentProtocol.js.map +1 -1
- package/dist/agent/types.d.ts +7 -0
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/agentOpenAI/openAiConfig.d.ts +2 -0
- package/dist/agentOpenAI/openAiConfig.d.ts.map +1 -1
- package/dist/agentOpenAI/openAiConfig.js +3 -0
- package/dist/agentOpenAI/openAiConfig.js.map +1 -1
- package/dist/agentOpenAI/openAiRuntime.d.ts +8 -0
- package/dist/agentOpenAI/openAiRuntime.d.ts.map +1 -1
- package/dist/agentOpenAI/openAiRuntime.js +293 -58
- package/dist/agentOpenAI/openAiRuntime.js.map +1 -1
- package/dist/agentRuntime/runtimeHealth.d.ts +1 -0
- package/dist/agentRuntime/runtimeHealth.d.ts.map +1 -1
- package/dist/agentv3/artifactStore.d.ts +5 -0
- package/dist/agentv3/artifactStore.d.ts.map +1 -1
- package/dist/agentv3/artifactStore.js +3 -0
- package/dist/agentv3/artifactStore.js.map +1 -1
- package/dist/agentv3/claudeMcpServer.d.ts.map +1 -1
- package/dist/agentv3/claudeMcpServer.js +125 -86
- package/dist/agentv3/claudeMcpServer.js.map +1 -1
- package/dist/agentv3/claudeRuntime.d.ts.map +1 -1
- package/dist/agentv3/claudeRuntime.js +147 -65
- package/dist/agentv3/claudeRuntime.js.map +1 -1
- package/dist/agentv3/claudeSseBridge.d.ts +6 -0
- package/dist/agentv3/claudeSseBridge.d.ts.map +1 -1
- package/dist/agentv3/claudeSseBridge.js +1 -0
- package/dist/agentv3/claudeSseBridge.js.map +1 -1
- package/dist/agentv3/sessionStateSnapshot.d.ts +23 -0
- package/dist/agentv3/sessionStateSnapshot.d.ts.map +1 -1
- package/dist/assistant/application/agentAnalyzeSessionService.d.ts +6 -0
- package/dist/assistant/application/agentAnalyzeSessionService.d.ts.map +1 -1
- package/dist/assistant/application/agentAnalyzeSessionService.js +9 -3
- package/dist/assistant/application/agentAnalyzeSessionService.js.map +1 -1
- package/dist/assistant/application/assistantApplicationService.d.ts.map +1 -1
- package/dist/assistant/application/assistantApplicationService.js +3 -1
- package/dist/assistant/application/assistantApplicationService.js.map +1 -1
- package/dist/cli-user/commands/report.js +64 -0
- package/dist/cli-user/commands/report.js.map +1 -1
- package/dist/cli-user/io/paths.d.ts +3 -0
- package/dist/cli-user/io/paths.d.ts.map +1 -1
- package/dist/cli-user/io/paths.js +6 -0
- package/dist/cli-user/io/paths.js.map +1 -1
- package/dist/cli-user/io/sessionStore.d.ts +1 -0
- package/dist/cli-user/io/sessionStore.d.ts.map +1 -1
- package/dist/cli-user/io/sessionStore.js +5 -0
- package/dist/cli-user/io/sessionStore.js.map +1 -1
- package/dist/cli-user/repl/renderer.d.ts +8 -0
- package/dist/cli-user/repl/renderer.d.ts.map +1 -1
- package/dist/cli-user/repl/renderer.js.map +1 -1
- package/dist/cli-user/services/cliAnalyzeService.d.ts +3 -0
- package/dist/cli-user/services/cliAnalyzeService.d.ts.map +1 -1
- package/dist/cli-user/services/cliAnalyzeService.js +103 -1
- package/dist/cli-user/services/cliAnalyzeService.js.map +1 -1
- package/dist/cli-user/services/turnPersistence.d.ts +0 -10
- package/dist/cli-user/services/turnPersistence.d.ts.map +1 -1
- package/dist/cli-user/services/turnPersistence.js +62 -0
- package/dist/cli-user/services/turnPersistence.js.map +1 -1
- package/dist/routes/agentReportRoutes.d.ts +1 -0
- package/dist/routes/agentReportRoutes.d.ts.map +1 -1
- package/dist/routes/agentReportRoutes.js +13 -2
- package/dist/routes/agentReportRoutes.js.map +1 -1
- package/dist/routes/agentResumeRoutes.d.ts.map +1 -1
- package/dist/routes/agentResumeRoutes.js +51 -5
- package/dist/routes/agentResumeRoutes.js.map +1 -1
- package/dist/routes/agentRoutes.d.ts.map +1 -1
- package/dist/routes/agentRoutes.js +524 -130
- package/dist/routes/agentRoutes.js.map +1 -1
- package/dist/scripts/verifyAgentSseScrolling.js +142 -2
- package/dist/scripts/verifyAgentSseScrolling.js.map +1 -1
- package/dist/services/agentEventStore.d.ts.map +1 -1
- package/dist/services/agentEventStore.js +13 -3
- package/dist/services/agentEventStore.js.map +1 -1
- package/dist/services/agentReportData.d.ts +3 -0
- package/dist/services/agentReportData.d.ts.map +1 -1
- package/dist/services/agentReportData.js.map +1 -1
- package/dist/services/agentResultNormalizer.d.ts +15 -3
- package/dist/services/agentResultNormalizer.d.ts.map +1 -1
- package/dist/services/agentResultNormalizer.js +344 -6
- package/dist/services/agentResultNormalizer.js.map +1 -1
- package/dist/services/analysisResultSnapshotPipeline.d.ts +3 -0
- package/dist/services/analysisResultSnapshotPipeline.d.ts.map +1 -1
- package/dist/services/analysisResultSnapshotPipeline.js +3 -0
- package/dist/services/analysisResultSnapshotPipeline.js.map +1 -1
- package/dist/services/analysisResultSnapshotStore.d.ts.map +1 -1
- package/dist/services/analysisResultSnapshotStore.js +34 -2
- package/dist/services/analysisResultSnapshotStore.js.map +1 -1
- package/dist/services/enterpriseSchema.d.ts.map +1 -1
- package/dist/services/enterpriseSchema.js +11 -0
- package/dist/services/enterpriseSchema.js.map +1 -1
- package/dist/services/evidence/evidenceContractBuilder.d.ts +11 -0
- package/dist/services/evidence/evidenceContractBuilder.d.ts.map +1 -0
- package/dist/services/evidence/evidenceContractBuilder.js +546 -0
- package/dist/services/evidence/evidenceContractBuilder.js.map +1 -0
- package/dist/services/finalResultQualityGate.d.ts +18 -0
- package/dist/services/finalResultQualityGate.d.ts.map +1 -0
- package/dist/services/finalResultQualityGate.js +283 -0
- package/dist/services/finalResultQualityGate.js.map +1 -0
- package/dist/services/htmlReportGenerator.d.ts +8 -1
- package/dist/services/htmlReportGenerator.d.ts.map +1 -1
- package/dist/services/htmlReportGenerator.js +129 -42
- package/dist/services/htmlReportGenerator.js.map +1 -1
- package/dist/services/persistAgentSession.d.ts +2 -0
- package/dist/services/persistAgentSession.d.ts.map +1 -1
- package/dist/services/persistAgentSession.js +17 -1
- package/dist/services/persistAgentSession.js.map +1 -1
- package/dist/services/processIdentity/identityContractMapper.d.ts +14 -0
- package/dist/services/processIdentity/identityContractMapper.d.ts.map +1 -0
- package/dist/services/processIdentity/identityContractMapper.js +135 -0
- package/dist/services/processIdentity/identityContractMapper.js.map +1 -0
- package/dist/services/processIdentity/types.d.ts +5 -0
- package/dist/services/processIdentity/types.d.ts.map +1 -1
- package/dist/services/processIdentity/types.js.map +1 -1
- package/dist/services/skillEngine/skillExecutor.d.ts +14 -2
- package/dist/services/skillEngine/skillExecutor.d.ts.map +1 -1
- package/dist/services/skillEngine/skillExecutor.js +133 -13
- package/dist/services/skillEngine/skillExecutor.js.map +1 -1
- package/dist/services/skillEngine/types.d.ts +2 -0
- package/dist/services/skillEngine/types.d.ts.map +1 -1
- package/dist/services/verifier/claimVerificationRunner.d.ts +20 -0
- package/dist/services/verifier/claimVerificationRunner.d.ts.map +1 -0
- package/dist/services/verifier/claimVerificationRunner.js +88 -0
- package/dist/services/verifier/claimVerificationRunner.js.map +1 -0
- package/dist/services/verifier/deterministicClaimVerifier.d.ts +8 -0
- package/dist/services/verifier/deterministicClaimVerifier.d.ts.map +1 -0
- package/dist/services/verifier/deterministicClaimVerifier.js +178 -0
- package/dist/services/verifier/deterministicClaimVerifier.js.map +1 -0
- package/dist/types/claimVerification.d.ts +38 -0
- package/dist/types/claimVerification.d.ts.map +1 -0
- package/dist/types/claimVerification.js +6 -0
- package/dist/types/claimVerification.js.map +1 -0
- package/dist/types/dataContract.d.ts +32 -0
- package/dist/types/dataContract.d.ts.map +1 -1
- package/dist/types/dataContract.js +7 -0
- package/dist/types/dataContract.js.map +1 -1
- package/dist/types/evidenceContract.d.ts +100 -0
- package/dist/types/evidenceContract.d.ts.map +1 -0
- package/dist/types/evidenceContract.js +6 -0
- package/dist/types/evidenceContract.js.map +1 -0
- package/dist/types/identityContract.d.ts +57 -0
- package/dist/types/identityContract.d.ts.map +1 -0
- package/dist/types/identityContract.js +6 -0
- package/dist/types/identityContract.js.map +1 -0
- package/dist/types/multiTraceComparison.d.ts +3 -0
- package/dist/types/multiTraceComparison.d.ts.map +1 -1
- package/package.json +3 -2
- package/skills/atomic/process_identity_resolver.skill.yaml +130 -1
- package/skills/atomic/process_slice_cpu_hotspots.skill.yaml +321 -0
- package/skills/atomic/startup_slow_reasons.skill.yaml +102 -17
- package/skills/composite/startup_analysis.skill.yaml +16 -0
- package/strategies/anr.strategy.md +2 -2
- package/strategies/game.strategy.md +1 -1
- package/strategies/general.strategy.md +1 -1
- package/strategies/prompt-openai-final-report-continuation-en.template.md +12 -0
- package/strategies/prompt-openai-final-report-continuation-zh.template.md +12 -0
- package/strategies/prompt-output-format.template.md +1 -1
- package/strategies/scrolling.strategy.md +1 -0
- package/strategies/startup.strategy.md +4 -1
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
# Copyright (C) 2024-2026 Gracker (Chris)
|
|
3
|
+
# This file is part of SmartPerfetto. See LICENSE for details.
|
|
4
|
+
|
|
5
|
+
# =============================================================================
|
|
6
|
+
# 进程 Slice CPU 热点(原子 Skill)
|
|
7
|
+
# =============================================================================
|
|
8
|
+
# 按进程统计 named slice 的实际 Running CPU time。不同于 wall duration,
|
|
9
|
+
# 这里把 slice 时间段和 thread_state=Running 区间求交,避免把睡眠、IO 等
|
|
10
|
+
# 非执行时间误算成 CPU 消耗。
|
|
11
|
+
|
|
12
|
+
name: process_slice_cpu_hotspots
|
|
13
|
+
version: "1.0"
|
|
14
|
+
type: atomic
|
|
15
|
+
category: cpu
|
|
16
|
+
tier: B
|
|
17
|
+
|
|
18
|
+
meta:
|
|
19
|
+
display_name: "进程 Slice CPU 热点"
|
|
20
|
+
description: "按进程聚合 named slice 的实际 Running CPU 时间"
|
|
21
|
+
icon: "query_stats"
|
|
22
|
+
tags: [cpu, slice, thread_state, running, hotspot, atomic]
|
|
23
|
+
|
|
24
|
+
triggers:
|
|
25
|
+
keywords:
|
|
26
|
+
zh: [slice CPU, 函数 CPU, 热点 slice, CPU 热点, Running 时间, named slice]
|
|
27
|
+
en: [slice cpu, function cpu, hot slices, cpu hotspots, running time, named slice]
|
|
28
|
+
patterns:
|
|
29
|
+
- ".*(slice|函数|方法).*(CPU|cpu|消耗|热点).*"
|
|
30
|
+
- ".*(CPU|cpu).*(slice|function|method|named).*"
|
|
31
|
+
|
|
32
|
+
prerequisites:
|
|
33
|
+
modules:
|
|
34
|
+
- sched
|
|
35
|
+
required_tables:
|
|
36
|
+
- slice
|
|
37
|
+
- thread_track
|
|
38
|
+
- thread
|
|
39
|
+
- process
|
|
40
|
+
- thread_state
|
|
41
|
+
|
|
42
|
+
identity:
|
|
43
|
+
policy: verify_if_present
|
|
44
|
+
scope: process
|
|
45
|
+
aliases: [package, process_name]
|
|
46
|
+
rewriteTo: recommended_process_name_param
|
|
47
|
+
|
|
48
|
+
inputs:
|
|
49
|
+
- name: package
|
|
50
|
+
type: string
|
|
51
|
+
required: false
|
|
52
|
+
description: "目标应用包名或进程名前缀"
|
|
53
|
+
- name: process_name
|
|
54
|
+
type: string
|
|
55
|
+
required: false
|
|
56
|
+
description: "目标进程名;当 package 为空时使用"
|
|
57
|
+
- name: upid
|
|
58
|
+
type: integer
|
|
59
|
+
required: false
|
|
60
|
+
description: "可选 trace 内进程 ID;优先级高于 package/process_name"
|
|
61
|
+
- name: slice_name
|
|
62
|
+
type: string
|
|
63
|
+
required: false
|
|
64
|
+
description: "可选 slice 名称过滤;默认字面包含匹配,包含 % 时按 SQL LIKE 模式匹配"
|
|
65
|
+
- name: thread_scope
|
|
66
|
+
type: string
|
|
67
|
+
required: false
|
|
68
|
+
default: all
|
|
69
|
+
description: "线程范围:all/main/render/main_render"
|
|
70
|
+
- name: start_ts
|
|
71
|
+
type: timestamp
|
|
72
|
+
required: false
|
|
73
|
+
description: "分析起始时间戳(ns),默认 trace_start()"
|
|
74
|
+
- name: end_ts
|
|
75
|
+
type: timestamp
|
|
76
|
+
required: false
|
|
77
|
+
description: "分析结束时间戳(ns),默认 trace_end()"
|
|
78
|
+
- name: min_cpu_ns
|
|
79
|
+
type: integer
|
|
80
|
+
required: false
|
|
81
|
+
default: 0
|
|
82
|
+
description: "聚合后最小 CPU 时间阈值(ns)"
|
|
83
|
+
- name: top_k
|
|
84
|
+
type: integer
|
|
85
|
+
required: false
|
|
86
|
+
default: 10
|
|
87
|
+
description: "返回 TopK 条目"
|
|
88
|
+
|
|
89
|
+
display:
|
|
90
|
+
level: detail
|
|
91
|
+
layer: list
|
|
92
|
+
title: "进程 Slice CPU 热点"
|
|
93
|
+
columns:
|
|
94
|
+
- name: process_name
|
|
95
|
+
label: "进程"
|
|
96
|
+
type: string
|
|
97
|
+
format: truncate
|
|
98
|
+
- name: slice_name
|
|
99
|
+
label: "Slice"
|
|
100
|
+
type: string
|
|
101
|
+
format: truncate
|
|
102
|
+
- name: count
|
|
103
|
+
label: "次数"
|
|
104
|
+
type: number
|
|
105
|
+
format: compact
|
|
106
|
+
- name: thread_count
|
|
107
|
+
label: "线程数"
|
|
108
|
+
type: number
|
|
109
|
+
format: compact
|
|
110
|
+
- name: sample_threads
|
|
111
|
+
label: "样例线程"
|
|
112
|
+
type: string
|
|
113
|
+
format: truncate
|
|
114
|
+
- name: total_cpu_ms
|
|
115
|
+
label: "CPU时间"
|
|
116
|
+
type: duration
|
|
117
|
+
format: duration_ms
|
|
118
|
+
unit: ms
|
|
119
|
+
- name: total_wall_ms
|
|
120
|
+
label: "Wall时间"
|
|
121
|
+
type: duration
|
|
122
|
+
format: duration_ms
|
|
123
|
+
unit: ms
|
|
124
|
+
- name: avg_cpu_ms
|
|
125
|
+
label: "平均CPU"
|
|
126
|
+
type: duration
|
|
127
|
+
format: duration_ms
|
|
128
|
+
unit: ms
|
|
129
|
+
- name: max_cpu_ms
|
|
130
|
+
label: "最大CPU"
|
|
131
|
+
type: duration
|
|
132
|
+
format: duration_ms
|
|
133
|
+
unit: ms
|
|
134
|
+
- name: cpu_efficiency_pct
|
|
135
|
+
label: "CPU/Wall"
|
|
136
|
+
type: percentage
|
|
137
|
+
format: percentage
|
|
138
|
+
- name: selected_cpu_share_pct
|
|
139
|
+
label: "所选CPU占比"
|
|
140
|
+
type: percentage
|
|
141
|
+
format: percentage
|
|
142
|
+
- name: first_ts
|
|
143
|
+
label: "首次出现"
|
|
144
|
+
type: timestamp
|
|
145
|
+
- name: last_ts
|
|
146
|
+
label: "最后出现"
|
|
147
|
+
type: timestamp
|
|
148
|
+
|
|
149
|
+
sql: |
|
|
150
|
+
WITH
|
|
151
|
+
raw_input AS (
|
|
152
|
+
SELECT
|
|
153
|
+
COALESCE(${start_ts}, trace_start()) AS raw_start_ts,
|
|
154
|
+
COALESCE(${end_ts}, trace_end()) AS raw_end_ts,
|
|
155
|
+
${upid} AS target_upid,
|
|
156
|
+
NULLIF(COALESCE(NULLIF('${process_name|}', ''), NULLIF('${package|}', '')), '') AS target_process,
|
|
157
|
+
NULLIF('${slice_name|}', '') AS target_slice,
|
|
158
|
+
CASE
|
|
159
|
+
WHEN '${thread_scope|all}' IN ('all', 'main', 'render', 'main_render') THEN '${thread_scope|all}'
|
|
160
|
+
ELSE 'all'
|
|
161
|
+
END AS thread_scope,
|
|
162
|
+
MAX(COALESCE(${min_cpu_ns|0}, 0), 0) AS min_cpu_ns,
|
|
163
|
+
MIN(MAX(COALESCE(${top_k|10}, 10), 1), 100) AS top_k
|
|
164
|
+
),
|
|
165
|
+
input AS (
|
|
166
|
+
SELECT
|
|
167
|
+
MIN(raw_start_ts, raw_end_ts) AS start_ts,
|
|
168
|
+
MAX(raw_start_ts, raw_end_ts) AS end_ts,
|
|
169
|
+
target_upid,
|
|
170
|
+
target_process,
|
|
171
|
+
target_slice,
|
|
172
|
+
thread_scope,
|
|
173
|
+
min_cpu_ns,
|
|
174
|
+
top_k
|
|
175
|
+
FROM raw_input
|
|
176
|
+
),
|
|
177
|
+
target_threads AS (
|
|
178
|
+
SELECT
|
|
179
|
+
p.upid,
|
|
180
|
+
p.pid,
|
|
181
|
+
p.name AS process_name,
|
|
182
|
+
t.utid,
|
|
183
|
+
t.tid,
|
|
184
|
+
COALESCE(t.name, '') AS thread_name
|
|
185
|
+
FROM process p
|
|
186
|
+
JOIN thread t ON t.upid = p.upid
|
|
187
|
+
CROSS JOIN input i
|
|
188
|
+
WHERE (
|
|
189
|
+
(
|
|
190
|
+
i.target_upid IS NOT NULL
|
|
191
|
+
AND p.upid = i.target_upid
|
|
192
|
+
)
|
|
193
|
+
OR (
|
|
194
|
+
i.target_upid IS NULL
|
|
195
|
+
AND (
|
|
196
|
+
i.target_process IS NULL
|
|
197
|
+
OR p.name GLOB i.target_process || '*'
|
|
198
|
+
OR p.name LIKE '%' || i.target_process || '%'
|
|
199
|
+
)
|
|
200
|
+
)
|
|
201
|
+
)
|
|
202
|
+
AND (
|
|
203
|
+
i.thread_scope = 'all'
|
|
204
|
+
OR (
|
|
205
|
+
i.thread_scope IN ('main', 'main_render')
|
|
206
|
+
AND (t.is_main_thread = 1 OR t.tid = p.pid)
|
|
207
|
+
)
|
|
208
|
+
OR (
|
|
209
|
+
i.thread_scope IN ('render', 'main_render')
|
|
210
|
+
AND (
|
|
211
|
+
t.name = 'RenderThread'
|
|
212
|
+
OR t.name = 'GPU completion'
|
|
213
|
+
OR t.name GLOB '[0-9]*.ui'
|
|
214
|
+
OR t.name GLOB '[0-9]*.raster'
|
|
215
|
+
)
|
|
216
|
+
)
|
|
217
|
+
)
|
|
218
|
+
),
|
|
219
|
+
candidate_slices AS (
|
|
220
|
+
SELECT
|
|
221
|
+
s.id,
|
|
222
|
+
s.name AS slice_name,
|
|
223
|
+
s.ts,
|
|
224
|
+
s.dur,
|
|
225
|
+
tt.upid,
|
|
226
|
+
tt.process_name,
|
|
227
|
+
tt.utid,
|
|
228
|
+
tt.thread_name
|
|
229
|
+
FROM slice s
|
|
230
|
+
JOIN thread_track track ON s.track_id = track.id
|
|
231
|
+
JOIN target_threads tt ON track.utid = tt.utid
|
|
232
|
+
CROSS JOIN input i
|
|
233
|
+
WHERE s.dur > 0
|
|
234
|
+
AND s.ts < i.end_ts
|
|
235
|
+
AND s.ts + s.dur > i.start_ts
|
|
236
|
+
AND (
|
|
237
|
+
i.target_slice IS NULL
|
|
238
|
+
OR (
|
|
239
|
+
INSTR(i.target_slice, '%') > 0
|
|
240
|
+
AND s.name LIKE i.target_slice
|
|
241
|
+
)
|
|
242
|
+
OR (
|
|
243
|
+
INSTR(i.target_slice, '%') = 0
|
|
244
|
+
AND INSTR(s.name, i.target_slice) > 0
|
|
245
|
+
)
|
|
246
|
+
)
|
|
247
|
+
),
|
|
248
|
+
per_slice_cpu AS (
|
|
249
|
+
SELECT
|
|
250
|
+
cs.id,
|
|
251
|
+
cs.process_name,
|
|
252
|
+
cs.slice_name,
|
|
253
|
+
cs.utid,
|
|
254
|
+
cs.thread_name,
|
|
255
|
+
MAX(cs.ts, i.start_ts) AS clipped_start_ts,
|
|
256
|
+
MIN(cs.ts + cs.dur, i.end_ts) AS clipped_end_ts,
|
|
257
|
+
MIN(cs.ts + cs.dur, i.end_ts) - MAX(cs.ts, i.start_ts) AS wall_ns,
|
|
258
|
+
COALESCE(SUM(
|
|
259
|
+
MIN(MIN(cs.ts + cs.dur, i.end_ts), ts.ts + ts.dur)
|
|
260
|
+
- MAX(MAX(cs.ts, i.start_ts), ts.ts)
|
|
261
|
+
), 0) AS cpu_ns
|
|
262
|
+
FROM candidate_slices cs
|
|
263
|
+
CROSS JOIN input i
|
|
264
|
+
LEFT JOIN thread_state ts ON ts.utid = cs.utid
|
|
265
|
+
AND ts.state = 'Running'
|
|
266
|
+
AND ts.dur > 0
|
|
267
|
+
AND ts.ts < MIN(cs.ts + cs.dur, i.end_ts)
|
|
268
|
+
AND ts.ts + ts.dur > MAX(cs.ts, i.start_ts)
|
|
269
|
+
GROUP BY
|
|
270
|
+
cs.id,
|
|
271
|
+
cs.process_name,
|
|
272
|
+
cs.slice_name,
|
|
273
|
+
cs.utid,
|
|
274
|
+
cs.thread_name,
|
|
275
|
+
cs.ts,
|
|
276
|
+
cs.dur,
|
|
277
|
+
i.start_ts,
|
|
278
|
+
i.end_ts
|
|
279
|
+
),
|
|
280
|
+
aggregate_cpu AS (
|
|
281
|
+
SELECT
|
|
282
|
+
process_name,
|
|
283
|
+
slice_name,
|
|
284
|
+
COUNT(*) AS count,
|
|
285
|
+
COUNT(DISTINCT utid) AS thread_count,
|
|
286
|
+
SUBSTR(GROUP_CONCAT(DISTINCT COALESCE(NULLIF(thread_name, ''), '<unnamed>')), 1, 240) AS sample_threads,
|
|
287
|
+
SUM(cpu_ns) AS total_cpu_ns,
|
|
288
|
+
SUM(wall_ns) AS total_wall_ns,
|
|
289
|
+
AVG(cpu_ns) AS avg_cpu_ns,
|
|
290
|
+
MAX(cpu_ns) AS max_cpu_ns,
|
|
291
|
+
MIN(clipped_start_ts) AS first_ts,
|
|
292
|
+
MAX(clipped_end_ts) AS last_ts
|
|
293
|
+
FROM per_slice_cpu
|
|
294
|
+
GROUP BY process_name, slice_name
|
|
295
|
+
HAVING SUM(cpu_ns) >= (SELECT min_cpu_ns FROM input)
|
|
296
|
+
),
|
|
297
|
+
selected_total AS (
|
|
298
|
+
SELECT SUM(total_cpu_ns) AS total_cpu_ns
|
|
299
|
+
FROM aggregate_cpu
|
|
300
|
+
)
|
|
301
|
+
SELECT
|
|
302
|
+
process_name,
|
|
303
|
+
slice_name,
|
|
304
|
+
count,
|
|
305
|
+
thread_count,
|
|
306
|
+
sample_threads,
|
|
307
|
+
ROUND(total_cpu_ns / 1e6, 2) AS total_cpu_ms,
|
|
308
|
+
ROUND(total_wall_ns / 1e6, 2) AS total_wall_ms,
|
|
309
|
+
ROUND(avg_cpu_ns / 1e6, 2) AS avg_cpu_ms,
|
|
310
|
+
ROUND(max_cpu_ns / 1e6, 2) AS max_cpu_ms,
|
|
311
|
+
ROUND(100.0 * total_cpu_ns / NULLIF(total_wall_ns, 0), 1) AS cpu_efficiency_pct,
|
|
312
|
+
ROUND(100.0 * total_cpu_ns / NULLIF((SELECT total_cpu_ns FROM selected_total), 0), 1) AS selected_cpu_share_pct,
|
|
313
|
+
printf('%d', first_ts) AS first_ts,
|
|
314
|
+
printf('%d', last_ts) AS last_ts
|
|
315
|
+
FROM aggregate_cpu
|
|
316
|
+
WHERE total_cpu_ns > 0
|
|
317
|
+
ORDER BY total_cpu_ns DESC
|
|
318
|
+
LIMIT (SELECT top_k FROM input)
|
|
319
|
+
|
|
320
|
+
output:
|
|
321
|
+
format: structured
|
|
@@ -71,17 +71,96 @@ steps:
|
|
|
71
71
|
type: duration
|
|
72
72
|
format: duration_ms
|
|
73
73
|
unit: ms
|
|
74
|
+
- name: ts
|
|
75
|
+
label: "启动开始时间(ns)"
|
|
76
|
+
type: timestamp
|
|
77
|
+
hidden: true
|
|
78
|
+
- name: dur
|
|
79
|
+
label: "启动耗时(ns)"
|
|
80
|
+
type: duration
|
|
81
|
+
hidden: true
|
|
82
|
+
- name: upid
|
|
83
|
+
label: "进程UPID"
|
|
84
|
+
type: number
|
|
85
|
+
hidden: true
|
|
74
86
|
sql: |
|
|
87
|
+
WITH startup_type_signals AS (
|
|
88
|
+
SELECT
|
|
89
|
+
st.startup_id,
|
|
90
|
+
MAX(CASE WHEN sl.name = 'bindApplication' THEN 1 ELSE 0 END) as has_bind_app,
|
|
91
|
+
MAX(CASE WHEN sl.name GLOB 'performCreate:*' THEN 1 ELSE 0 END) as has_perform_create,
|
|
92
|
+
MAX(CASE WHEN sl.name GLOB 'handleRelaunchActivity*'
|
|
93
|
+
OR sl.name GLOB 'relaunchActivity*' THEN 1 ELSE 0 END) as has_relaunch
|
|
94
|
+
FROM android_startup_threads st
|
|
95
|
+
JOIN thread_track tt ON tt.utid = st.utid
|
|
96
|
+
JOIN slice sl ON sl.track_id = tt.id
|
|
97
|
+
WHERE st.is_main_thread = 1
|
|
98
|
+
AND sl.ts + sl.dur > st.ts AND sl.ts < st.ts + st.dur
|
|
99
|
+
AND (sl.name = 'bindApplication'
|
|
100
|
+
OR sl.name GLOB 'performCreate:*'
|
|
101
|
+
OR sl.name GLOB 'handleRelaunchActivity*'
|
|
102
|
+
OR sl.name GLOB 'relaunchActivity*')
|
|
103
|
+
GROUP BY st.startup_id
|
|
104
|
+
),
|
|
105
|
+
process_age AS (
|
|
106
|
+
SELECT
|
|
107
|
+
s.startup_id,
|
|
108
|
+
MAX(CASE
|
|
109
|
+
WHEN p.start_ts IS NOT NULL
|
|
110
|
+
AND p.start_ts >= s.ts - 5000000000
|
|
111
|
+
AND p.start_ts <= s.ts + s.dur
|
|
112
|
+
THEN 1 ELSE 0
|
|
113
|
+
END) as process_created_during_startup
|
|
114
|
+
FROM android_startups s
|
|
115
|
+
LEFT JOIN android_startup_processes asp ON asp.startup_id = s.startup_id
|
|
116
|
+
LEFT JOIN process p ON p.upid = asp.upid
|
|
117
|
+
GROUP BY s.startup_id
|
|
118
|
+
),
|
|
119
|
+
startup_process AS (
|
|
120
|
+
SELECT startup_id, MAX(upid) as upid
|
|
121
|
+
FROM android_startup_processes
|
|
122
|
+
GROUP BY startup_id
|
|
123
|
+
),
|
|
124
|
+
validated AS (
|
|
125
|
+
SELECT
|
|
126
|
+
s.startup_id,
|
|
127
|
+
s.package,
|
|
128
|
+
s.ts,
|
|
129
|
+
CASE
|
|
130
|
+
WHEN COALESCE(sts.has_bind_app, 0) = 1 THEN 'cold'
|
|
131
|
+
WHEN COALESCE(sts.has_perform_create, 0) = 1 AND COALESCE(sts.has_bind_app, 0) = 0 THEN 'warm'
|
|
132
|
+
WHEN COALESCE(sts.has_relaunch, 0) = 1 THEN 'warm'
|
|
133
|
+
WHEN COALESCE(pa.process_created_during_startup, 0) = 1 THEN 'cold'
|
|
134
|
+
ELSE s.startup_type
|
|
135
|
+
END as startup_type,
|
|
136
|
+
s.dur,
|
|
137
|
+
ttd.time_to_initial_display,
|
|
138
|
+
ttd.time_to_full_display,
|
|
139
|
+
COALESCE(sp.upid, (
|
|
140
|
+
SELECT p2.upid
|
|
141
|
+
FROM process p2
|
|
142
|
+
WHERE p2.name GLOB s.package || '*'
|
|
143
|
+
ORDER BY p2.start_ts DESC
|
|
144
|
+
LIMIT 1
|
|
145
|
+
)) as upid
|
|
146
|
+
FROM android_startups s
|
|
147
|
+
LEFT JOIN startup_process sp ON sp.startup_id = s.startup_id
|
|
148
|
+
LEFT JOIN android_startup_time_to_display ttd USING (startup_id)
|
|
149
|
+
LEFT JOIN startup_type_signals sts USING (startup_id)
|
|
150
|
+
LEFT JOIN process_age pa USING (startup_id)
|
|
151
|
+
)
|
|
75
152
|
SELECT
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
153
|
+
startup_id,
|
|
154
|
+
package,
|
|
155
|
+
startup_type,
|
|
156
|
+
ts,
|
|
157
|
+
dur,
|
|
158
|
+
upid,
|
|
159
|
+
ROUND(dur / 1e6, 1) as dur_ms,
|
|
160
|
+
ROUND(time_to_initial_display / 1e6, 1) as ttid_ms,
|
|
161
|
+
ROUND(time_to_full_display / 1e6, 1) as ttfd_ms
|
|
162
|
+
FROM validated
|
|
163
|
+
ORDER BY dur DESC
|
|
85
164
|
save_as: startup_overview
|
|
86
165
|
optional: true
|
|
87
166
|
|
|
@@ -91,6 +170,7 @@ steps:
|
|
|
91
170
|
- id: slow_reason_checks
|
|
92
171
|
type: atomic
|
|
93
172
|
name: "慢启动原因检测"
|
|
173
|
+
condition: startup_overview.data.length > 0
|
|
94
174
|
display:
|
|
95
175
|
level: key
|
|
96
176
|
layer: list
|
|
@@ -113,11 +193,16 @@ steps:
|
|
|
113
193
|
type: string
|
|
114
194
|
sql: |
|
|
115
195
|
WITH startup_info AS (
|
|
116
|
-
SELECT
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
196
|
+
SELECT
|
|
197
|
+
startup_id,
|
|
198
|
+
package,
|
|
199
|
+
ts,
|
|
200
|
+
dur,
|
|
201
|
+
startup_type,
|
|
202
|
+
upid
|
|
203
|
+
FROM ${startup_overview}
|
|
204
|
+
ORDER BY dur DESC
|
|
205
|
+
LIMIT 1
|
|
121
206
|
),
|
|
122
207
|
main_thread AS (
|
|
123
208
|
SELECT t.utid, t.tid FROM thread t
|
|
@@ -310,7 +395,7 @@ steps:
|
|
|
310
395
|
JOIN thread_track tt2 ON ba.track_id = tt2.id
|
|
311
396
|
JOIN main_thread mt2 ON tt2.utid = mt2.utid
|
|
312
397
|
WHERE ba.name = 'bindApplication'
|
|
313
|
-
AND ba.ts
|
|
398
|
+
AND ba.ts + ba.dur > si.ts AND ba.ts < si.ts + si.dur
|
|
314
399
|
)
|
|
315
400
|
) WHERE cp_count > 3
|
|
316
401
|
|
|
@@ -341,7 +426,7 @@ steps:
|
|
|
341
426
|
JOIN thread_track tt2 ON ba.track_id = tt2.id
|
|
342
427
|
JOIN main_thread mt2 ON tt2.utid = mt2.utid
|
|
343
428
|
WHERE ba.name = 'bindApplication'
|
|
344
|
-
AND ba.ts
|
|
429
|
+
AND ba.ts + ba.dur > si.ts AND ba.ts < si.ts + si.dur
|
|
345
430
|
AND ts_inner.ts >= ba.ts AND ts_inner.ts < ba.ts + ba.dur
|
|
346
431
|
) THEN ts_inner.dur ELSE 0 END) > SUM(ts_inner.dur) / 2 THEN 1 ELSE 0 END as in_bind_app,
|
|
347
432
|
-- SR04 是否已覆盖:futex wait 中有多少被 Lock contention slice 时间重叠解释
|
|
@@ -410,7 +495,7 @@ steps:
|
|
|
410
495
|
FROM slice ba
|
|
411
496
|
JOIN thread_track tt_ba ON ba.track_id = tt_ba.id
|
|
412
497
|
JOIN main_thread mt_ba ON tt_ba.utid = mt_ba.utid
|
|
413
|
-
JOIN startup_info si ON ba.ts
|
|
498
|
+
JOIN startup_info si ON ba.ts + ba.dur > si.ts AND ba.ts < si.ts + si.dur
|
|
414
499
|
JOIN slice s ON s.track_id = ba.track_id
|
|
415
500
|
AND s.ts >= ba.ts AND s.ts < ba.ts + ba.dur
|
|
416
501
|
AND s.dur > 5000000 -- > 5ms
|
|
@@ -131,6 +131,22 @@ steps:
|
|
|
131
131
|
- name: type_display
|
|
132
132
|
label: "启动类型"
|
|
133
133
|
type: string
|
|
134
|
+
- name: startup_type
|
|
135
|
+
label: "修正后类型"
|
|
136
|
+
type: string
|
|
137
|
+
hidden: true
|
|
138
|
+
- name: original_type
|
|
139
|
+
label: "原始类型"
|
|
140
|
+
type: string
|
|
141
|
+
hidden: true
|
|
142
|
+
- name: type_reclassified
|
|
143
|
+
label: "类型已修正"
|
|
144
|
+
type: number
|
|
145
|
+
hidden: true
|
|
146
|
+
- name: type_confidence
|
|
147
|
+
label: "类型置信度"
|
|
148
|
+
type: string
|
|
149
|
+
hidden: true
|
|
134
150
|
- name: dur_ms
|
|
135
151
|
label: "耗时"
|
|
136
152
|
type: duration
|
|
@@ -108,7 +108,7 @@ fetch_artifact(artifactId, detail="rows", offset=0, limit=50)
|
|
|
108
108
|
|--------|------|------|--------|
|
|
109
109
|
| Q4 Sleeping 极高 | >80% | **主线程被阻塞**(ANR 最常见原因) | → 第二步:用 blocked_functions 定位 |
|
|
110
110
|
| Q3 Runnable 高 | >30% | CPU 饥饿——可运行但得不到 CPU | → 检查 `sched_latency`、`cpu_health`、后台进程抢占 |
|
|
111
|
-
| Q1+Q2 Running 高 | >70% | CPU-bound——主线程在执行重计算 | → 检查 `main_thread_slices
|
|
111
|
+
| Q1+Q2 Running 高 | >70% | CPU-bound——主线程在执行重计算 | → 检查 `main_thread_slices`,并调用 `invoke_skill("process_slice_cpu_hotspots", { process_name, start_ts, end_ts, thread_scope: "main" })` 定位主线程热点函数/slice 的 Running CPU time |
|
|
112
112
|
| 混合 | 无明显主导 | 多因素共同导致 | → 依次排查 Q4→Q3→Q1 |
|
|
113
113
|
|
|
114
114
|
### 第二步:当 Q4 占比高时 — 用 blocked_functions + 线程状态定位
|
|
@@ -197,4 +197,4 @@ fetch_artifact(artifactId, detail="rows", offset=0, limit=50)
|
|
|
197
197
|
- 忽略 `wakeup_chain` 数据(这是定位间接依赖链的关键)
|
|
198
198
|
- 把所有 ANR 统一用同一个决策路径分析,不区分 ANR 类型
|
|
199
199
|
- 忽略 `app_freeze_check`(应用完全冻结 vs 部分响应是重要区分)
|
|
200
|
-
- 不交叉检查 CPU/内存/IO 系统上下文就下结论
|
|
200
|
+
- 不交叉检查 CPU/内存/IO 系统上下文就下结论
|
|
@@ -100,7 +100,7 @@ invoke_skill("mali_gpu_power_state")
|
|
|
100
100
|
| CPU 频率下降 | `invoke_skill("thermal_throttling")` | 游戏长时间运行容易触发热节流 |
|
|
101
101
|
| 内存压力 | `invoke_skill("memory_analysis")` | 游戏内存占用大,可能触发 LMK |
|
|
102
102
|
| CPU 调度 | `invoke_skill("cpu_analysis")` | 游戏线程调度到小核会造成帧率波动 |
|
|
103
|
-
| 线程/进程 CPU 利用率 | `invoke_skill("cpu_thread_utilization_period")` / `invoke_skill("cpu_process_utilization_period")` | 判断 UnityMain/GameThread/RenderThread 是否 CPU-bound |
|
|
103
|
+
| 线程/进程 CPU 利用率 | `invoke_skill("cpu_thread_utilization_period")` / `invoke_skill("cpu_process_utilization_period")`;需要函数/slice 级热点时补 `invoke_skill("process_slice_cpu_hotspots", { process_name, start_ts, end_ts })` | 判断 UnityMain/GameThread/RenderThread 是否 CPU-bound,并用 Running CPU time 定位 named slice 热点 |
|
|
104
104
|
| 功耗归因 | `invoke_skill("wattson_thread_power_attribution")` | 仅在 power_rails + cpu_freq_idle 可用时做线程能耗归因 |
|
|
105
105
|
| 独立 GL swap 间隔 | `invoke_skill("gl_standalone_swap_jank")` | NativeActivity/GLSurfaceView 或引擎自管 swap 时检查生产端 present 节奏 |
|
|
106
106
|
|
|
@@ -19,7 +19,7 @@ keywords: []
|
|
|
19
19
|
|
|
20
20
|
| 用户关注方向 | 推荐路径 | 说明 |
|
|
21
21
|
|-------------|---------|------|
|
|
22
|
-
| **CPU / 调度 / 线程** | `invoke_skill("cpu_analysis")` → 如果发现 throttling → `invoke_skill("thermal_throttling")` |
|
|
22
|
+
| **CPU / 调度 / 线程** | `invoke_skill("cpu_analysis")` → 需要函数/slice CPU 热点时 `invoke_skill("process_slice_cpu_hotspots", { process_name: "<包名或进程名>" })` → 如果发现 throttling → `invoke_skill("thermal_throttling")` | 用 Running CPU time 区分真实计算热点和 wall-time 阻塞,再交叉检查热节流和 CPU 频率 |
|
|
23
23
|
| **内存 / OOM / 泄漏** | `invoke_skill("memory_analysis")` → 如果有 heap dump → `invoke_skill("android_heap_graph_summary")` → 如果有 LMK → `invoke_skill("lmk_analysis")` → 如果涉及 GPU 内存 → `invoke_skill("dmabuf_analysis")` | 层层深入内存问题;heap graph 用 retained/cumulative size 定位 retainer |
|
|
24
24
|
| **IO / 磁盘 / 存储** | `invoke_skill("block_io_analysis")` 或 `invoke_skill("io_pressure")` | 磁盘 IO 和系统 IO 压力 |
|
|
25
25
|
| **GPU / 渲染** | `invoke_skill("gpu_analysis")` | GPU 频率、利用率、Fence 等待 |
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
|
|
2
|
+
<!-- Copyright (C) 2024-2026 Gracker (Chris) | SmartPerfetto -->
|
|
3
|
+
|
|
4
|
+
System check: every analysis phase is completed/skipped, but there is still no complete user-facing final report.
|
|
5
|
+
|
|
6
|
+
Now output only the final report body. The first line must be `## Final Conclusion`. Do not call tools, do not call update_plan_phase, do not narrate the process, and do not output phase-by-phase logs.
|
|
7
|
+
|
|
8
|
+
The report must include: final conclusion, key evidence chain, root-cause breakdown, ruled-out factors, recommendations, and confidence/limitations.
|
|
9
|
+
|
|
10
|
+
Do not merely restate phase summaries; synthesize the collected concrete values and evidence into a readable conclusion.
|
|
11
|
+
|
|
12
|
+
Length requirement: at most 700 English words. Use 2-3 bullets per section; do not expand into a phase-by-phase log, do not copy artifact tables, do not output the evidence table index, and do not repeat raw SQL. If the evidence is sufficient, conclude directly.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
|
|
2
|
+
<!-- Copyright (C) 2024-2026 Gracker (Chris) | SmartPerfetto -->
|
|
3
|
+
|
|
4
|
+
系统校验:所有分析阶段已经 completed/skipped,但当前还没有面向用户的完整最终报告。
|
|
5
|
+
|
|
6
|
+
请现在只输出最终报告正文;第一行必须是 `## 综合结论`。不要再调用工具,不要再调用 update_plan_phase,不要解释过程,不要输出“验证逻辑/现在进入 Phase/完成综合结论输出/分阶段证据摘要”。
|
|
7
|
+
|
|
8
|
+
报告必须包含:综合结论、关键证据链、根因拆解、已排除因素、优化建议、置信度/限制。
|
|
9
|
+
|
|
10
|
+
不要只复述阶段摘要;必须把已采集到的具体数值和证据串成可读结论。
|
|
11
|
+
|
|
12
|
+
长度要求:最多 1200 个中文字符。每个小节 2-3 条要点即可;不要展开逐阶段流水账,不要复制 artifact 表格,不要重复 SQL 原文,不要输出证据表索引。若证据已经足够,直接收束。
|
|
@@ -84,7 +84,7 @@ graph LR
|
|
|
84
84
|
```
|
|
85
85
|
|
|
86
86
|
### 结论结构
|
|
87
|
-
|
|
87
|
+
结论必须完整但克制:优先输出能支撑决策的证据链,避免把已经展示过的大表逐行搬进最终报告。中文目标长度控制在约 2500-3500 字符,英文目标长度控制在约 1200-1800 words;如果证据很多,用聚合表和证据索引压缩,不要生成会在 token 上限处截断的超长报告。
|
|
88
88
|
|
|
89
89
|
1. **概览**: 一句话总结性能状况。如果架构检测置信度 < 80%,在概览中标注(如"⚠️ 架构检测置信度 50%,分析策略可能不完全匹配"),帮助用户理解分析的局限性
|
|
90
90
|
2. **关键发现**: 按严重程度排列的发现列表(含根因推理链 + 📚 背景知识)
|
|
@@ -224,6 +224,7 @@ invoke_skill("scrolling_analysis", { start_ts: "<trace_start>", end_ts: "<trace_
|
|
|
224
224
|
| UI thread 时间分解 | `invoke_skill("frame_ui_time_breakdown")` | 看 UI thread 在每帧的耗时分布 |
|
|
225
225
|
| 每帧阻塞调用 | `invoke_skill("frame_blocking_calls")` | 将掉帧帧与 Binder/GC/锁竞争/futex/文件 IO 阻塞区间做重叠匹配 |
|
|
226
226
|
| CPU process/thread 周期利用率 | `invoke_skill("cpu_process_utilization_period")` / `invoke_skill("cpu_thread_utilization_period")` | 用于 workload_heavy、后台抢占、线程归因 |
|
|
227
|
+
| 进程 slice CPU 热点 | `invoke_skill("process_slice_cpu_hotspots", { process_name, start_ts, end_ts })` | 用 `thread_state=Running` 求交,确认掉帧窗口内真正消耗 CPU 的 named slice |
|
|
227
228
|
| CPU cluster 拓扑 | `invoke_skill("cpu_cluster_mapping_view")` | 解释大小核分布,辅助 small_core_placement |
|
|
228
229
|
| GPU work period | `invoke_skill("android_gpu_work_period_track")` | 只有 `gpu_work_period` capability 可用时才做 GPU active region 判断 |
|
|
229
230
|
| Mali power state | `invoke_skill("mali_gpu_power_state")` | Mali 设备专用;无数据时标注设备/trace 不支持 |
|
|
@@ -102,12 +102,14 @@ plan_template:
|
|
|
102
102
|
| 热启动 (hot) | 两者均不存在 → 保留 Perfetto 原始分类 | Activity.onRestart() → onStart() → onResume() |
|
|
103
103
|
|
|
104
104
|
**判定逻辑(优先级从高到低):**
|
|
105
|
-
1. 如果 Skill 返回的 `startup_type` 已经过重分类(`startup_events_in_range` 的 SQL
|
|
105
|
+
1. 如果 Skill 返回的 `startup_type/type_display` 已经过重分类(`startup_events_in_range` 的 SQL 层重分类,或 `startup_quality.issue_codes` 包含 `R009_TYPE_RECLASSIFIED`),直接信任;除非同一条 SQL 明确复现了 Skill 的 overlap 口径并证明修正信号不存在,否则不得推翻。
|
|
106
106
|
2. 否则检查 trace 信号:`bindApplication` 存在 → cold;仅 `performCreate:*` 存在 → warm;均无 → hot
|
|
107
107
|
3. 热启动无正向信号(没有专属的 trace slice),仅靠排除法判定——这是合理的,因为热启动不触发 Activity 重建
|
|
108
108
|
|
|
109
109
|
**⚠️ LMK 边界场景:** 进程被 LMK 回收后重启时,ActivityManager 可能仍持有 Activity 记录,导致 Perfetto 报告 `warm`。但 `bindApplication` slice 存在说明进程经历了完整初始化(Zygote fork → handleBindApplication),实为 cold start。此时**必须以 `bindApplication` 信号为准**,覆盖 Perfetto 原始分类。
|
|
110
110
|
|
|
111
|
+
**⚠️ 验证口径陷阱:** `bindApplication` 可能早于 `android_startups.ts` 约几十到数百毫秒开始。用 `thread_slice.ts BETWEEN start_ts AND end_ts` 的窄窗口查询返回 0 行,不能证明 `bindApplication` 不存在。若要自行验证,必须使用 `android_startup_threads` 与 `slice` 的 overlap 条件(`sl.ts + sl.dur > st.ts AND sl.ts < st.ts + st.dur`),或至少把起点扩展到 `start_ts - 500ms`。当 `startup_analysis` 已给出 `type_display=冷启动`、`type_reclassified=1`、`startup_breakdown.reason=bind_application` 或 `R009_TYPE_RECLASSIFIED` 时,结论必须按冷启动写,不得输出“R009 误判/维持温启动”。
|
|
112
|
+
|
|
111
113
|
#### 启动场景关键 Stdlib 表
|
|
112
114
|
|
|
113
115
|
写 execute_sql 时优先使用(完整列表见方法论模板):`android_startup_opinionated_breakdown`、`android_garbage_collection_events`、`android_oom_adj_intervals`、`android_screen_state`、`slice_self_dur`、`cpu_process_utilization_in_interval(ts, dur)`、`cpu_frequency_counters`、`android_dvfs_counter_stats`
|
|
@@ -131,6 +133,7 @@ invoke_skill("startup_analysis", { enable_startup_details: false })
|
|
|
131
133
|
可能的根因:异步帧渲染排队、SurfaceFlinger 合成延迟、GPU 渲染耗时、dequeueBuffer 等待。结论中必须量化说明 gap 中各阶段的耗时占比。
|
|
132
134
|
- **R009_TYPE_RECLASSIFIED**(启动类型重分类):如果温启动存在 bindApplication slice,说明进程实际被重建过,可能是冷启动被误分类。分析时应质疑启动类型并说明重分类依据。
|
|
133
135
|
- **温启动 + bindApplication 矛盾**:即使未触发 R009,如果主线程热点中出现 bindApplication(478ms+),也应主动质疑:温启动不应有 Application 初始化开销。可能原因:① 进程被回收后重启(实为冷启动);② framework atrace 标记不准确。
|
|
136
|
+
- **禁止反向误判**:如果 `startup_analysis.get_startups` 显示 `type_display=冷启动`,且 `startup_breakdown` 包含 `bind_application` 耗时,后续任何 raw SQL 只有在使用 overlap/扩展窗口并命中同一进程主线程后,才允许挑战冷启动结论。窄窗口 0 行只能写成“该 SQL 口径未覆盖 bindApplication 起点”,不能写成“bindApplication 不存在”。
|
|
134
137
|
|
|
135
138
|
**Phase 2 — 获取启动详情(需要传参):**
|
|
136
139
|
```
|