想象你家楼下新开了一家体检中心。以前你只有头晕发热才去挂急诊,临时量血压、抽血、拍片,看完开药走人——可身体的慢性损耗,第二天会不会再来,没人知道。现在医院送了你一块智能手环:从戴上那一刻起,它 24 小时记录心率、血氧、睡眠,一个月后医生拉出一张曲线图,一眼就看出你哪天夜里心脏悄悄超了负荷。持续性能剖析(Continuous Profiling) 干的就是这件事——它不再等系统“生病”才去查,而是给每个应用戴上“性能手环”,7×24 小时记录每个函数的 CPU、内存消耗,再把数据画成一张叫火焰图的“身体热力图”。本篇文章会用“后厨计时员”这个贯穿始终的比喻,带你从零看懂持续剖析的原理、工具与落地姿势。

岗位关联

对 AI 从业者而言,持续剖析是排查性能瓶颈、支撑云原生系统稳定性的必备技能——学会它,你就拥有了把“系统卡顿”变成“一张图说清病根”的硬核能力。

目录
  1. 可视化演示
  2. 核心概念:从“急诊体检”到“全天候手环”
  3. 火焰图:一张“菜品耗时海报”
  4. 采集架构:后厨里的“巡场秒表”
  5. 数据存储:剖析数据的“档案库”
  6. 平台对比:Pyroscope 与 Parca 的“对台戏”
  7. 可观测集成:三支柱缺的那块“化验单”
  8. 落地实践:让剖析成为日常制度
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

演示持续性能剖析(Continuous Profiling)的火焰图生成、采集架构、数据存储与可观测性集成四阶段,步进切换查看剖析数据如何从应用采集、存储并转化为火焰图,帮助定位性能瓶颈。

本节配有交互动效(进入视口后自动加载,约 3KB)。

持续性能剖析四阶段 火焰图横向宽度代表资源占比 Agent 持续采集应用剖析数据 数据存储支撑时序分析 热点 = 最宽栈帧 接入可观测性平台实现常态化治理

核心概念:从“急诊体检”到“全天候手环”

想象小区门口那家体检中心。过去你只有头晕发热才挂急诊,医生临时量血压、拍片子,看完开药走人——身体慢性的损耗第二天会不会再来,没人知道。持续性能剖析(Continuous Profiling)想改变的就是这个场景:它不追求“有事才查”,而是给软件系统戴上一块 24 小时不摘的智能手环,从应用启动那一刻起,不断记录每个“器官”(函数)的实时负荷,把每一次“心跳”都变成可回放的数据。

传统 Profiling(剖析)在线上事故时手动触发,采样几秒到几分钟,定位完就关闭。它像急诊,能救命但看不到慢性病。持续剖析则把同样的采样动作常驻在生产环境,7×24 小时运行,默认采样频率往往只有 100Hz 甚至更低,单个进程额外 CPU 开销能控制在 1% 以内,却能覆盖全量请求和全部时段,让“偶发瓶颈”和“渐近劣化”都无处遁形。实现上,剖析器周期性中断线程、抓取当前调用栈,累加每个函数的命中次数。

采样开销占比=f×c\text{采样开销占比} = f \times c

1. 采样频率 f:每秒抓取多少次调用栈,单位是 Hz。传统按需剖析可以每秒上千次,持续剖析通常压到 100Hz 以下。

ff

2. 单次采样耗时 c:抓取一次调用栈需要的 CPU 时间,一般在微秒级。eBPF 等内核态采集可以进一步压小它。

cc

3. 二者相乘:每秒因剖析消耗的 CPU 时间。比如 f=100、c=10μs,乘积仅占一个 CPU 核的千分之一。

f×cf \times c

手环之所以能戴着睡觉,是因为它的测量足够轻——持续剖析能成为生产环境标配,靠的正是把开销压到几乎无感。

火焰图:一张“菜品耗时海报”

走进后厨,墙上挂着一张花花绿绿的海报:横着一排排彩色横条,像堆积木一样从下往上垒。最宽的那道横条旁边写着“水煮鱼”,宽得占了大半面墙。原来这是餐厅的“菜品耗时海报”——每段横条是一道菜(函数),横条越宽,说明厨师们累计做这道菜花的时间越多。这就是火焰图(Flame Graph)。

理解火焰图有三个关键点。第一,x 轴不是时间顺序,而是采样占比:所有同层横条宽度之和等于 100% 采样,所以 x 轴方向无意义,只有宽度有意义。第二,y 轴自底向上代表调用栈从根到叶,比如 main → handle_request → query_db → mysql_connect,底层是入口,顶层是被调用的具体函数。第三,相同调用栈会被合并成一条横条,颜色只是按函数名哈希随机分配,不表示严重程度。找性能热点,就看顶部哪些横条又宽又平——那正是 CPU 时间聚集的地方。

P(node)=S(node)Stotal×100%P(node) = \frac{S(node)}{S_{total}} \times 100\%

1. S(node):某个函数(或调用栈)在采样中被命中的次数,比如一小时内被记录到 800 次。

S(node)S(node)

2. S_{total}:同一时间段内所有采样总数,比如 10000 次。分母把所有函数归一化到同一把尺子下。

StotalS_{total}

3. 比值与百分比:两者相除再乘 100%,得到横条宽度。占比 8% 就画 8% 的宽度,一眼可读。

S(node)Stotal×100%\frac{S(node)}{S_{total}} \times 100\%

后厨主管每天看一眼耗时海报,就知道该优化哪道菜;你打开火焰图,同样能一眼锁定拖慢服务的“厨艺短板”。

采集架构:后厨里的“巡场秒表”

如何在完全不打扰厨师的前提下,统计每个人花在各道菜上的时间?餐厅老板想了个办法:让领班带着秒表,每隔五分钟悄悄巡场一次,看一眼每个厨师手头正在做哪道菜,在小本子上记一笔。厨师从不停下手里的活,领班也不问话——这就是“采样”的精髓。

技术上的采样原理与此同构:剖析器启动一个定时器(通常是 SIGPROF 信号),每隔固定间隔中断目标线程,记录它此刻的程序计数器(PC)和完整调用栈,然后立刻恢复执行。现代实现还常用 eBPF 在 Linux 内核态完成采样,连用户态的频繁中断都省了。采集到的数据由 Agent 探针统一收集,并打上 service、version、pod 等标签,再批量上报给后端存储。采样间隔 Δt 越小,时间分辨率越高,但开销也越大,因此需要在两者间权衡。

n=TΔtn = \frac{T}{\Delta t}

1. 总时长 T:持续剖析运行的时间长度,比如 24 小时或一个发布窗口。

TT

2. 采样间隔 Δt:两次采样之间的时间差。100Hz 对应 Δt=10ms,10Hz 对应 100ms。

Δt\Delta t

3. 样本总数 n:T 除以 Δt 得到总样本数。样本越多,统计越接近真实占比,但传输与存储成本也随之上升。

TΔt\frac{T}{\Delta t}

领班一天能记下几万笔“某某在做什么菜”,却不用任何一位厨师停下手——好的采样 Agent 就是如此透明。

数据存储:剖析数据的“档案库”

后厨的小本子一天就写满好几本,字迹潦草、无法检索。老板雇了一位档案管理员,定下规矩:每笔记录必须按“日期 + 菜品 + 厨灶编号”归类,字迹统一压缩成标准表格,再按标签建索引。从此,“上周三晚上八点哪道菜最耗时”这种问题,翻索引一查便知。

剖析数据的存储设计正是这套档案逻辑。每个样本都带时间戳和标签,按时间序列入库;为了控制成本,Parca 把原始剖面数据放进对象存储(如 S3),再用类似 Thanos 的 TSDB 做标签索引与查询加速;Pyroscope 则自研了内嵌存储引擎。两者都做两件关键优化:一是按调用栈聚合压缩,相同栈只存一份计数;二是符号化延迟——采集时只记内存地址,等查询时才翻译成函数名,大幅降低采集端开销。

D=R×s×N×d×λD = R \times s \times N \times d \times \lambda

1. 采样率 R 与单样本大小 s:每秒每个进程产生多少样本、每个样本原始多大(栈深度越深越大)。

R×sR \times s

2. 进程数 N 与保留天数 d:被剖析的服务实例越多、数据保留越久,存储压力线性增长。

N×dN \times d

3. 压缩因子 λ:调用栈聚合与压缩后的体积系数,对象存储方案可做到 1/30 以下。

λ\lambda

档案管理好了,“上个月 12 号晚高峰哪个函数在喘粗气”随口就能查——这正是持续剖析数据给你的超能力。

平台对比:Pyroscope 与 Parca 的“对台戏”

有两家档案系统公司来竞标。A 公司说:“我把档案柜直接放你家库房,全套设备我包了,三天就能跑起来。”B 公司说:“档案我帮你存进云端大仓库,你只用一个检索框就能查所有分店的数据,长期成本还更低。”A 公司是 Pyroscope,B 公司是 Parca。

Pyroscope 出身 Grafana Labs 生态,提供多语言 SDK 与 eBPF 两种采集方式,服务端自带存储、一体化部署,适合中小团队快速上手。Parca 由 Polar Signals 发起,是 CNCF 项目,主打海量数据下的低成本:依赖对象存储 + 时序索引,eBPF 是主要采集手段,查询协议兼容 pprof,与 Grafana 深度集成。选型时可以用加权评分法,把生态、成本、社区三个维度按团队优先级打分。

Score=w1E+w2S+w3CScore = w_1 E + w_2 S + w_3 C

1. 权重 w_k:反映团队对每个维度的重视程度,三者相加为 1。存储预算紧张的团队给 w_2 调高。

w1+w2+w3=1w_1 + w_2 + w_3 = 1

2. 生态集成 E:与 Grafana、Prometheus 等现有监控栈的契合程度。

EE

3. 存储成本 S:按对象存储与自建存储的 TCO 打分,规模越大权重越高。

SS

4. 社区活跃度 C:CNCF 治理、贡献者数量、生产案例丰富度。

CC

你家餐厅只有几十个厨师,选 A 公司图省事;等开成连锁,再换 B 公司降成本——架构选型没有最好,只有适配。

可观测集成:三支柱缺的那块“化验单”

病人发烧了,体温计(指标)告诉你“38.5℃“;病人主诉(日志)说”头疼“;病历流程单(链路追踪)记录”挂了内科、拍了 CT、取了药”。可医生还是说不清病因——直到血液化验单(火焰图)出来:白细胞偏高,原来是细菌感染。指标负责报警,日志负责描述,链路负责还原路径,而剖析负责给出根因证据。

这就是持续剖析在可观测性体系中的位置:它常被称为“第四根支柱”,或者说是对原有三支柱的补齐。落地形态很清晰:Prometheus 告警触发 CPU 突增 → 点击跳转到 Grafana 中该时段的火焰图 → 看到某个序列化函数占了 60% CPU → 再结合链路数据确认是哪个接口触发的。Grafana 目前已原生支持 Pyroscope 与 Parca 数据源,实现指标、日志、链路、剖析四类数据同屏联动,诊断从“猜”变成“看”。

R=1ΔtR = \frac{1}{\Delta t}

1. 时间分辨率 R:能区分到多短时间内的性能变化,单位与 Hz 等价。

RR

2. 采样间隔 Δt:两次采样的间隔。压测时用高分辨率抓毛刺,日常治理用低分辨率省成本。

Δt\Delta t

3. 倒数关系:Δt=10ms 时 R=100Hz;Δt=1s 时 R=1Hz。二者此消彼长。

1Δt\frac{1}{\Delta t}

有了“化验单”,三支柱才真正闭环:指标找到“事发现场”,火焰图指出“作案手法”,链路还原“作案路径”。

落地实践:让剖析成为日常制度

后厨最终把“记工册”升级成了常态制度:每天自动记录、每周自动生成工时报告、每月复盘会上对照海报讨论改进项。老板发现,制度跑起来之后,后厨的效率再也没出现过悄悄滑坡——因为任何一条线的异常,都会在一周内被时间和数据揪出来。

落地持续剖析也遵循同样的节奏。选型:小团队用 Pyroscope 快速起步,大规模或存储敏感场景选 Parca。部署:通过 Helm 以 DaemonSet 形态在每个 K8s 节点部署一个采集 Agent,服务端按集群规模分体部署,再接入 Grafana 统一入口。实践:把“剖析自身 CPU 开销低于 5%”作为上线验收标准,在预发环境对比开关剖析前后的性能差异。治理:发布新版本后对比前后火焰图,做容量规划与成本账单拆分,把火焰图审查纳入例行巡检。

pprofiling≤5%p_{\text{profiling}} \leq 5\%

1. p_profiling:剖析模块自身占用的 CPU 开销比例,用压测环境开关对比测得。

pprofilingp_{\text{profiling}}

2. ≤ 5%:社区公认的可接受上限。低于它,用户无感;高于它,需要降采样率或改用 eBPF。

≤5%\leq 5\%

3. 验收动作:发布前在预发环境开/关剖析各跑 10 分钟,对比两项吞吐量差异。

p=开剖析耗时−关剖析耗时关剖析耗时×100%p = \frac{\text{开剖析耗时} - \text{关剖析耗时}}{\text{关剖析耗时}} \times 100\%

制度一旦固化,后厨效率不可能悄悄滑坡——系统性能也一样,常态化剖析就是那条“不允许滑坡”的护栏。

AI 应用场景

场景一:SRE 生产事故根因定位

阶段:故障诊断与根因分析

解决的问题:传统排障靠“指标报警 + 人肉猜”,经常在多个服务间来回跳。有了持续剖析,SRE 收到 CPU 告警后,直接打开告警时段的火焰图,看到 json.Marshal 横条异常宽大,结合链路确认是高并发下大对象序列化导致,十分钟内定位到代码行。

具体案例:某电商大促期间,订单服务 CPU 飙到 95%,但 QPS 并无明显增长。持续剖析显示 regexp.MatchString 占 47% CPU,进一步发现日志脱敏逻辑对每个字段都跑了一遍正则,改为预编译后 CPU 降至 40%。整个过程从告警到修复发布不到半小时。

场景二:云原生容量规划与成本治理

阶段:资源优化与成本分析

解决的问题:K8s 集群中大量 Pod 的 CPU Request 是拍脑袋定的,造成资源浪费。持续剖析数据可以按 namespace、deployment 标签聚合出真实的 CPU 时间分布,发现哪些服务长期处于低水位,从而指导缩容与降配。

具体案例:某团队对 200 个微服务开启持续剖析一个月后,发现 12 个服务的 CPU 利用率长期低于 10%,火焰图显示大部分时间花在空轮询和锁等待上。据此将 12 个服务的副本数从 5 降到 3,每月节省约 3 万元云成本。

场景三:发布前性能回归防护

阶段:CI/CD 质量门禁

解决的问题:新版本代码合并后,某些函数性能悄悄劣化,往往到线上才暴露。持续剖析结合发布流程,对新旧版本的火焰图做 diff,能自动发现“新增的热点函数”,在 CI 阶段就拦截性能回归。

具体案例:某后端团队在每次发版后自动拉取 30 分钟剖析数据,与基线版本对比。一次前端框架升级后,火焰图 diff 显示 component_render 占比从 5% 升至 25%,随即回滚并缩小了升级范围,避免了线上卡顿事故。

Python 演示

python51 行
"""持续剖析核心机制演示:模拟采样与火焰图聚合"""import randomimport timefrom collections import Counter, defaultdict # 模拟一组可观测的"调用栈模板",栈底到栈顶表示 main -> handler -> dbSTACK_TEMPLATES = [    ("main", "handle_request", "parse_json"),    ("main", "handle_request", "query_db", "mysql_connect"),    ("main", "handle_request", "query_db", "cache_get"),    ("main", "handle_request", "render_template"),    ("main", "health_check"),    ("main", "background_job", "compress_log"),]  class SamplingProfiler:    """周期采样器:每隔 interval 秒,随机抓取一个线程的当前调用栈"""     def __init__(self, interval=0.05):        self.interval = interval        self.samples = Counter()     def run(self, seconds):        deadline = time.time() + seconds        while time.time() < deadline:            stack = random.choice(STACK_TEMPLATES)            self.samples[stack] += 1            time.sleep(self.interval)     def print_flame_graph(self):        total = sum(self.samples.values())        if total == 0:            return        # 将叶子样本向所有祖先层累加,才能得到每层的横条宽度        node_weight = defaultdict(int)        for stack, count in self.samples.items():            depth = len(stack)            for i in range(depth):                node_weight[stack[: i + 1]] += count        for stack, weight in sorted(node_weight.items(), key=lambda kv: (len(kv[0]), kv[0])):            pct = weight / total * 100            indent = "  " * len(stack)            print(f"{indent}{stack[-1]:<16} {pct:5.1f}%  {'#' * int(pct / 2)}")  if __name__ == "__main__":    profiler = SamplingProfiler(interval=0.02)    print("正在采样 2 秒...")    profiler.run(2)    profiler.print_flame_graph()
目的:用随机调用栈模拟“采样”过程,并演示火焰图聚合的核心逻辑——把叶子函数的样本向父层累加,再按占比打印出层级缩进的简易火焰图。
  1. STACK_TEMPLATES = [...]预先定义可能出现的调用栈模板,模拟真实的函数调用路径,每条路径从 main 开始。
  2. self.samples[stack] += 1每次采样把当前调用栈的计数加一,这就是“持续记录”在代码里最朴素的样子。
  3. time.sleep(self.interval)控制采样间隔,间隔越小单位时间内的数据越密,但模拟程序也跑得越慢。
  4. node_weight[stack[: i + 1]] += count关键一步:把叶子栈的样本数向所有祖先前缀累加,火焰图各层宽度才成立。
  5. pct = weight / total * 100把计数转成占比,火焰图横条宽度就是按这个百分比画的。

常见误区

误区我以为火焰图就像时序折线图,从左到右是请求从开始到结束的时间线,横条宽的说明执行时间长,所以总习惯看 x 轴方向上的变化趋势。

正解火焰图的 x 轴完全没有时间顺序的含义,只表示样本占比。比如 query_db 横条占 40% 宽,是指 40% 的采样都命中了它,而不是它在时间线上占据了前 40%。就像菜品耗时海报,横条宽度代表累计工时占比,跟哪道菜先上无关。

为何常见:因为平时看折线图、柱状图都默认 x 轴有顺序,加上火焰图名字里有“图”字,很容易把横轴类比成时间轴。

误区我听说剖析要频繁打断线程抓堆栈,在开发环境都嫌卡,放到生产环境 7×24 小时跑,那不得把 CPU 拖垮?所以一直不敢在生产开启。

正解持续剖析的核心设计目标就是极低开销。100Hz 采样、单次微秒级抓取、加上 eBPF 内核态采集和符号延迟解析,单个进程的 CPU 开销通常能控制在 1%~3%,远小于 5% 的业界预算线。而且采样是“看一眼就走”,不阻塞业务逻辑。

为何常见:人们用过传统的按需剖析器,那是每秒上千次采样、要跑几分钟的“重家伙”,自然以为持续剖析也是这个量级,忽略了采样率的调节空间。

误区我以为火焰图的价值在于看函数之间怎么互相调用,像 UML 时序图一样。每次拿到火焰图都试图沿着横条去理清调用顺序。

正解火焰图确实按调用栈组织层级,但它的核心产出不是“谁调用了谁”,而是“时间都花在谁身上”。自底向上的结构只是为了区分上下文,同一函数出现在不同调用路径会被合并成一条横条,突出的是聚合后的占比,而非调用拓扑。

为何常见:因为 y 轴的层级结构和“调用栈”概念外观相似,初学者容易把它误解为架构图或调用链图,忽略了横条宽度才是主角。

误区我觉得持续剖析和生产环境的监控一样,数据越多越精准,于是把采样频率拉到 1000Hz,想着多抓几倍样本,火焰图肯定更详细。

正解采样率过高会让剖析自身开销非线性增长,变成“为了监控而拖垮业务”。持续剖析调用的是概率统计:100Hz 采样 1 分钟就有 6000 个样本,对占比分析已经足够;真正要抓瞬时毛刺时,可以按需临时调高,而不是全程高频。

为何常见:直觉上“更多数据=更准”,但忽略了采样理论的收益递减,以及剖析开销与业务抢占 CPU 之间的矛盾。

误区持续剖析不就是 APM 吗?都是监控应用性能的,Prometheus 加链路追踪都有了,为什么还要单独上一个剖析系统?

正解APM 关注请求级指标(响应时间、错误率、事务追踪),回答“哪个接口慢”;持续剖析关注资源在函数级的时间分布,回答“为什么慢”。类比来说,APM 是“这次就诊花了多少钱、排了多久队”,剖析是“哪个器官在超负荷运转”。二者互补而非替代。

为何常见:因为两者都展示调用栈、都用于监控,功能边界在外观上有重叠,容易让人误以为多此一举。

面试题

Q1. 火焰图中,横条宽度的直接含义是什么?

单选题 · easy

  • A.函数执行的时间顺序
  • B.函数在采样中的占比← 正确答案
  • C.函数本身的代码行数
  • D.函数调用的嵌套深度

答案:B。火焰图横条宽度等于该函数被采样命中的次数占总采样的比例,类似菜品耗时海报中横条的“累计工时占比”。A 是误区(x 轴不是时间),C、D 与采样占比无关。

Q2. 持续剖析与传统按需剖析最主要的区别是什么?

单选题 · easy

  • A.开发工具不同
  • B.常驻生产持续采集← 正确答案
  • C.编程语言不同
  • D.展示形式不同

答案:B。传统剖析在故障时手动触发、采样几分钟就关闭;持续剖析像全天候手环一样常驻生产环境,7×24 小时采集。工具、语言、展示形式都不是本质差异。

Q3. 某持续剖析系统采样频率为 100Hz,这意味着什么?

单选题 · mid

  • A.每秒采集 100 次调用栈← 正确答案
  • B.每 100 秒采集一次样本
  • C.同时采样 100 个线程状态
  • D.采样 100 个进程的调用栈

答案:A。100Hz 表示每秒触发 100 次采样,即采样间隔 Δt=10ms。它衡量的是采样密度而非线程数、进程数。与“巡场秒表”类比,就是领班每秒看 100 次表。

Q4. 火焰图中,y 轴从下到上代表什么?

单选题 · mid

  • A.函数的执行时间顺序
  • B.调用栈从根到叶的走向← 正确答案
  • C.内存地址从低到高排列
  • D.线程优先级由高到低排列

答案:B。y 轴底部是调用入口(如 main),越往上越是叶子函数。它展示的是调用层级,不是时间序或地址序。看热点时自下而上找“顶部宽平”区域。

Q5. 关于 Pyroscope 与 Parca 的说法,正确的是哪项?

单选题 · mid

  • A.二者都属于 CNCF 孵化项目
  • B.Parca 依赖对象存储与 TSDB 架构← 正确答案
  • C.Pyroscope 只支持 Go 语言编写
  • D.Parca 不支持 eBPF 采集方式

答案:B。Parca 采用对象存储加 TSDB 索引的架构以降低海量数据成本;Pyroscope 被 Grafana Labs 收购且自身带存储,并非 CNCF 项目。二者都支持多语言与 eBPF。

Q6. 在 Kubernetes 中,持续剖析的采集端通常以何种方式部署?

单选题 · mid

  • A.部署在独立物理机集群
  • B.K8s 节点级 DaemonSet← 正确答案
  • C.只在开发环境临时手动启动
  • D.由业务代码主动嵌入调用

答案:B。DaemonSet 保证每个 K8s 节点恰好运行一个采集 Agent,配合 eBPF 便能覆盖该节点上所有 Pod,无需改业务代码,这是云原生下最主流的部署形态。

Q7. 为什么持续剖析对“自身开销”如此敏感?

单选题 · hard

  • A.生产常驻开销会直接影响业务← 正确答案
  • B.为了降低云服务器租赁成本
  • C.为了减少日志文件的磁盘占用
  • D.为了加快剖析工具自身的分析速度

答案:A。持续剖析 7×24 小时运行在业务进程旁,自身 CPU 开销直接与业务争抢资源。业界认为低于 5% 才是安全预算,否则治理工具本身变成新的性能瓶颈。

Q8. 持续剖析数据接入可观测性平台后,能带来哪些能力?

多选题 · easy

  • A.指标告警后看对应时段火焰图← 正确答案
  • B.慢请求直接关联到剖析样本← 正确答案
  • C.通过剖析界面直接修改业务代码
  • D.把剖析数据用于长期容量规划← 正确答案

答案:ABD。接入后可实现“告警→火焰图→根因”联动、慢请求与剖析样本关联、长期容量治理。持续剖析只负责观测,不提供代码修改能力,因此 C 错误。

Q9. 关于火焰图的正确说法有哪些?

多选题 · mid

  • A.横轴表示真实时间先后顺序
  • B.横条宽度等于采样占比大小← 正确答案
  • C.相同调用栈会合并成一个横条← 正确答案
  • D.垂直方向代表调用栈的嵌套层级← 正确答案

答案:BCD。火焰图 x 轴方向无时间含义,只按占比分配宽度,A 错误。相同调用栈合并、y 轴表示调用栈层级,都是火焰图的基本规则。

Q10. 哪些手段能有效降低持续剖析在生产的开销?

多选题 · hard

  • A.适当降低 CPU 采样频率配置← 正确答案
  • B.把函数符号化延后到查询阶段← 正确答案
  • C.只采样异常报错的请求线程
  • D.用标签按服务选择性采集剖析← 正确答案

答案:ABD。降采样率、延迟符号化、按需选择性采集都是业界常用的降开销手段。而“只采样异常线程”会破坏概率统计基础,火焰图的占比分析将失去意义,因此 C 错误。