AI Agent实现原理与实践(六):Observability & Operations

1. 前言 在上一篇文章中,我们深入剖析了 Permission, Approval & Sandbox 的设计——Agent 如何在拥有强大执行能力的同时,通过多层防御体系保证安全可控。如果说 Agent Loop 是 Agent 的"心跳",Tool System 是"双手",Context Management 是"记忆系统",SubAgent System 是"团队协作能力",Permission & Sandbox 是"免疫系统",那么 Observability & Operations(可观测性与运维)就是 Agent 的"神经系统"——它决定了 Agent 在生产环境中能否被监控、追踪、调试和治理。 当 Agent 真正部署到生产环境——作为 CLI 工具被数千名开发者日常使用、作为后台服务持续运行数周、作为编码助手修改关键代码——可观测性变成了Agent的基本能力。 可观测性不是简单的打日志,报个监控,而是一组更根本的问题: Agent 的一次运行,事后能不能完整回放和审计? Agent 正在做什么,当前处于什么状态,有没有卡住? 子 Agent、后台任务、定时调度——这些异步执行单元能不能被追踪? 出问题后,第一现场在哪里?如何区分是模型问题、工具问题、上下文问题还是系统问题? Token 消耗、API 延迟、工具调用耗时——这些成本指标能不能被量化和管理? 会话能不能被恢复、归档、导出、切换?这些运维动作是不是系统的一等能力? 本文是 Agent 实现原理系列的第六篇,继续参考 Codex CLI、Claude Code、nanobot、pi 四个主流开源项目的实现,从工程角度总结 Agent 可观测性与运维体系的设计原则和关键权衡。 2. 可观测性是 Agent Runtime 的骨架 2.1 从"打点日志"到"多层信号体系" Agent 的运行过程不是一条直线,而是一棵分叉的树——有主会话、有子 Agent、有后台任务、有定时调度、有工具调用链、有压缩边界、有权限决策点。单靠几条零散的 log,在出问题时根本无法还原"当时到底发生了什么"。 更深一层看,可观测性之于 Agent,就像飞行数据记录仪之于飞机——不是为了日常飞行时盯着看,而是为了两件事: 事后可恢复:会话中断了能继续,系统崩溃了能重建状态 事中可诊断:运行时能判断 Agent 是正常推理、卡在工具执行、还是在等待用户审批 因此,一个 production-grade Agent Runtime 的可观测性,不是"有空再补点日志",而是和主执行链同等级的基础设施。它至少需要覆盖五种不同粒度:会话级(transcript、session metadata)、任务级(background task status、task output)、工具级(tool call 轨迹、shell output、permission 事件)、平台级(analytics、tracing、metrics)、运维级(状态快照、健康检查、成本追踪)。 ...

June 7, 2026 · Skyan

AI Agent实现原理与实践(五):Permission, Approval & Sandbox

1. 前言 在上一篇文章中,我们深入剖析了 SubAgent System 的设计——Agent 如何将复杂任务拆解、委托给多个专职子 Agent 并行执行。如果说 Agent Loop 是 Agent 的"心跳",Tool System 是 Agent 的"双手",Context Management 是 Agent 的"记忆系统",SubAgent System 是 Agent 的"团队协作能力",那么 Permission, Approval & Sandbox(权限、审批与沙箱系统)就是 Agent 的"免疫系统"——它决定了 Agent 在拥有强大执行能力的同时,是否会对宿主环境造成不可逆的破坏。 这其实是一个在Agent规模化之后出现的工程难题,在 Demo 阶段,让 Agent “能跑起来"容易,但当 Agent 真正接入开发者的生产环境——能读写文件、执行 shell 命令、访问网络、修改 Git 历史——安全就不再是"锦上添花”,而是"生死攸关"。 Anthropic 曾经内部维护了一个事故日志,专门记录 Agent 行为失控的案例1:Agent 因误解指令而删除了远程 Git 分支;Agent 把工程师的 GitHub 认证 token 上传到了内部计算集群;Agent 试图对生产数据库执行迁移操作。这些事故的共同特征不是"模型意图作恶",而是模型过度热心(overeager)——它以用户没有预料到的方式主动采取了行动。 更隐蔽的威胁来自 prompt injection:攻击者在网页、文件或工具输出中植入指令,劫持 Agent 偏离用户任务、转向攻击者的目标。2025 年 10 月,Anthropic 发表的 Claude Code 沙箱技术博客开门见山地指出:即使是一次成功的 prompt injection,如果发生在 sandbox 之内,攻击者也什么都拿不到2。 ...

June 7, 2026 · Skyan

AI Agent实现原理与实践(四):SubAgent System

1. 前言 在上一篇文章中,我们深入剖析了 Context Management 的设计——Agent 如何在有限的上下文窗口中管理记忆、压缩历史和治理信息。如果说 Agent Loop 是 Agent 的"心跳",Tool System 是 Agent 的"双手",Context Management 是 Agent 的"记忆系统",那么 SubAgent System(子Agent系统)就是 Agent 的"团队协作能力"——它决定了单个 Agent 能否将复杂任务拆解、委托给多个专职子 Agent 并行执行,再将结果汇合为一个整体产出。 这是 Agent 从"单兵作战"升级为"团队协作"的关键一跃。考虑一个真实的编程场景:用户说"帮我重构这个模块,把数据库层从 PostgreSQL 迁移到 MySQL,同时重写所有测试"。在传统单 Agent 模式下,主 Agent 需要先读 Schema、再改 ORM 代码、再迁移数据、再改写测试——每一步的结果都灌进同一个上下文窗口,很快上下文就会膨胀到填满。更糟的是,这些任务天然可并行(改 ORM 和写测试完全可以同时进行),但单 Agent 只能串行。 SubAgent System 解决了这个根本矛盾,在保持主会话可控的前提下,将独立子任务剥离到独立的执行上下文中,并行推进,结果按需回流。这个设计目标看似简单,但要在工程上做好,涉及一套完整的子系统设计:子 Agent 如何创建?父子之间共享什么、隔离什么?子 Agent 之间如何通信?结果如何汇合?worktree 隔离做到什么程度? 最近这一年来,SubAgent System 的研究已经从实验室走向了超大规模的生产实践。2026 年初,Anthropic 研究员 Nicholas Carlini 进行了一项轰动一时的实验1:用 16 个并行 Claude Agent、近 2,000 个 session、两周时间,从零写出一个 10 万行的 C 编译器。 这个编译器能通过 GCC torture test suite 99% 的测试用例,能成功编译 Linux 6.9 内核、QEMU、FFmpeg、SQLite、Postgres 和 Redis。API 费用约 $20,000。有点小贵,但对比一个资深工程师团队两周的人力成本,已经进入了"经济上可行"的区间。与此同时,Anthropic 工程团队也公开了他们在构建**长运行 Agent(Long-running Agent)**时的系统性实践经验2,提出了一套让 Agent 跨越多个上下文窗口持续工作的 Harness 设计。 ...

June 7, 2026 · Skyan

AI Agent实现原理与实践(三):Context Management

1. 前言 在上一篇文章中,我们深入剖析了 Tool System 的设计——Agent 如何定义、注入、执行和回写工具调用。如果说 Agent Loop 是 Agent 的"心跳",Tool System 是 Agent 的"双手",那么 Context Management(上下文管理)就是 Agent 的"记忆系统"——它决定了 Agent 能记住什么、忘记什么、以及如何在有限的上下文窗口中高效组织信息。 1.1 从 Prompt Engineering 到 Context Engineering 过去几年,应用 AI 领域的焦点一直是 Prompt Engineering——如何写出更好的 prompt,让模型产出更好的结果。但随着 Agent 系统从单轮对话演进为多轮、多工具、长生命周期的自主运行,一个更根本的问题浮现了出来:不只是 prompt 写得好不好,而是进入模型上下文窗口的每一段信息,是否都值得占据那有限的注意力预算。 Anthropic 在其 2025 年的工程博客中正式提出了 Context Engineering 这个概念,将其定义为 Prompt Engineering 的自然演进1: Prompt Engineering 解决的是"怎么写 prompt",Context Engineering 解决的是"什么信息该进入上下文窗口,以最大化达成目标行为的概率"。 这个转变的核心原因是:一个在 loop 中运行的 Agent,每轮都在产生越来越多的数据——tool result、思考过程、中间决策、用户反馈——这些数据都有可能对下一轮推理有用,但不一定都值得放进有限的上下文窗口。Context Engineering 的本质,就是从不断膨胀的信息熵中,反复筛选出那组最小的高信号 token 集合。 1.2 上下文窗口没有免费午餐:Context Rot 这个筛选之所以必要,根源在于 LLM 架构层面的一个基本约束。Anthropic 的研究指出,LLM 存在 上下文衰减(context rot) 现象:随着上下文窗口中的 token 数量增加,模型准确回忆其中信息的能力会下降1。 ...

June 6, 2026 · Skyan

AI Agent实现原理与实践(二):Tool System

1. 前言 在上一篇文章中,我们深入剖析了 Agent Loop 的核心原理——Agent 如何在"思考-行动-观察"的循环中持续迭代,直到完成任务。如果说 Agent Loop 是 Agent 系统的"心跳",那么 Tool System(工具系统)就是 Agent 的"双手"——它决定了 Agent 能做什么、怎么做、以及做的过程中如何保证安全和可控。 在2025年以前,大模型应用流行的形态还是Chatbot,这类应用只能说不能做:它可以给你建议,但无法读你的代码、改你的文件、执行你的命令、搜索你的文档。Tool System 把 LLM 从一个"聊天机器"升级为"能干活的行者"。但这也带来了新的工程挑战:工具怎么定义,才能既让模型理解又让运行时高效执行?工具怎么注入,才能既全面又不撑爆上下文窗口?工具怎么执行,才能既灵活又安全?外部工具(MCP)怎么接入,才能和内建工具一样丝滑? 本文是 Agent 实现原理系列的第二篇,继续参考 Codex CLI、Claude Code、nanobot、pi 四个主流开源项目的实现,从工程角度总结 Tool System 的设计原则和关键权衡。 2. Tool System 的本质 2.1 从"函数调用"到"Tool Runtime" 在深入架构之前,先要澄清一个根本问题:工具到底是什么? 传统软件开发是在两个确定性系统之间建立契约——调用 getWeather("NYC") 每次都会以完全相同的方式获取天气。但 Agent 是非确定性的:同一个用户问题,它可能选择调用天气工具,也可能凭通用知识回答,甚至可能产生幻觉或误解工具用法。Anthropic 在其工具设计最佳实践文章中给出了一个精辟的定义1:工具是确定性系统与非确定性智能体之间的契约。 这个定义意味着,为 Agent 编写工具需要从根本上转变思维——不能再像为其他开发者写 API 那样设计工具,而必须面向一个"聪明但偶尔会犯糊涂、上下文有限、需要引导"的调用者来设计。如果你的工具让模型感到困惑、给了它太多无关信息、或者参数命名模糊,那不是模型的问题,是契约设计的问题。带着这个视角来看后面的 Tool System 架构,很多设计取舍的原因就清晰了。 一个最简单的 tool 实现,可以写成这样: def execute_tool(name, args): tool = tools[name] return tool(args) 这种naïve的实现距离一个"能在真实产品中安全运行的 Tool Runtime"还有很大差距。真实场景需要回答的问题包括: ...

June 6, 2026 · Skyan

AI Agent实现原理与实践(一):Agent Loop

导言 自2025年下半年以来,AI大模型的应用热点从chatbot转变到了智能体Agent。以Claude Code,Codex,OpenClaw等为代表的Agent风靡一时,成为业界热点话题。对于开发者而言,一旦习惯使用Agent来开发代码,就不会再回到过去那种、code completion或者chatbot的开发模式了。随之而来的一个疑问就是,Agent和AI chatbot这样的软件有什么本质区别?事实上,主要经过深入学习和研究Agent原理之后,每个人都会发现一个现象:那就是Agent的开发原理和过去所有的软件都不相同,它是一种AI时代、新的、纯新、毫无争议的新软件架构范式。每一个希望深入应用Agent架构的开发者、希望深入了解Agent的学习者、希望深入优化Agent的高级架构师,都必须先了解Agent的实现原理和最佳实践,才能深刻体会到这种崭新的思想,才能在AI时代快速变化的迷雾中,找到一丝微弱的亮光,指引开发者们前行。 本系列文章以著名的四个Agent项目:Claude Code,OpenAI Codex,Pi,Nanobot作为基础案例,分别介绍Agent的主要机制的设计原理和最佳实践。共分为六章:「Agent Loop」,「Tool System」,「Context Management」,「SubAgent System」,「Permission, Approval & Sandbox」以及「Observability & Operations」,这六章可以从机制上剖析Agent的基本架构。但实际Agent应用的内涵远不止这些内容,Agent的工业级落地还会面临更为复杂的情况,这可能是另外一个话题了。 1. 前言 随着2022年底以ChatGPT为代表的LLM(大语言模型)爆发式发展,AI Agent(智能体)迅速从概念走向工程实践。从早期简单的单轮对话工具,到如今能够自主规划、调用工具、持续迭代的编程Agent(如Cursor、Claude Code、Codex CLI),Agent已经成为大模型应用落地的核心形态。正如OpenAI在其官方博客中所说,Agent Loop是连接用户、模型和工具的枢纽。 作为Agent系统的核心机制,Agent Loop(智能体循环)决定了Agent如何思考、如何行动、如何与外部环境交互。这个循环的本质是:Agent接收用户输入,查询模型进行推理,模型要么产生最终回复,要么请求工具调用;Agent执行工具后将结果回灌到prompt中,再次查询模型——如此反复,直到模型停止发出工具调用、产出面向用户的assistant message为止。这个assistant message不仅是对用户的回应,更标志着Agent Loop的一个终止状态:从Agent的视角看,它的工作已经完成,控制权交还用户。 它看似简单——不过是一个"调模型、执行工具、再调模型"的循环——但要在真实产品中稳定、高效、可扩展地运行,却涉及大量精妙的工程设计和架构取舍。比如,随着对话增长,prompt长度会不断增加,而每个模型都有上下文窗口(context window)限制,因此上下文窗口管理是Agent的核心职责之一。此外,Agent执行的工具调用会修改本地环境(如读写文件),所以Agent的"输出"远不止assistant message,还包括它实际产生的代码变更等副作用。 本文是Agent实现原理系列的第一篇,将从工程实现的角度,深入剖析Agent Loop的核心原理。我们将参考Codex CLI、Claude Code、nanobot、pi等主流开源项目的实现,抽象出Agent Loop的通用模型,分析其关键设计点和工程权衡。 2. Agent Loop的本质 2.1 从"会调LLM的程序"到"Agent Runtime" 一个最朴素的Agent实现,可以写成下面这样: while true: response = call_llm(messages, tools) if response has tool_calls: results = execute_tools(response.tool_calls) messages += [response, results] else: return response.content 这段代码确实构成了Agent Loop的核心骨架,但它距离一个"能在真实产品中运行的Agent Runtime"还有很大差距。真实场景需要回答的问题包括: ...

April 25, 2026 · Skyan

策略调度引擎的演进

在搜索、推荐和广告等高复杂度在线系统中,“策略算法的调度执行”是支撑系统智能的基础能力。为了高效运行各种策略算法,几乎所有大型平台最终都走向了相同的抽象:将策略算法封装为算子(Operator),并通过 DAG(有向无环图)驱动其有序并发执行。这种调度引擎的设计已经历二十余年的演进,并在实践中不断向更高层次的智能和复杂性发展。 策略调度引擎通常位于算法密集型在线服务的执行框架之中。下图展示了一个典型推荐系统的策略流程(搜索和广告系统也类似): graph TD A[解析请求参数] --> B[召回算法1] A --> C[召回算法2] A --> D[召回算法3] B --> E[去重] C --> E D --> E E --> F[过滤] G[历史曝光] --> F F --> H[排序] H --> I[重排序] I --> J[返回结果] 上述流程只是推荐系统的一个高层抽象。真实系统中,这样的流程会跨越数十甚至上百个微服务,每个微服务内部都可能执行一个多步骤策略流水线,规模可达几十到几百万行代码。在这种背景下,如何高效开发各阶段策略,并以流程化方式调度执行,成为系统设计的基础问题。 第一代引擎——算子调度(2004~2014) 第一代引擎诞生于桌面互联网兴起到移动互联网爆发前夜的十年间。当时以搜索和广告为代表的复杂在线系统,开始采用面向对象和微服务的设计思想,并把策略算法抽象为算子对象,由调度引擎顺序执行。 这一代的核心特征是: 策略抽象为算子,实现配置化的调度执行 算子化的设计带来了低耦合、高内聚的好处。推荐各阶段复杂算法被封装为独立算子,不同策略可以交给不同的开发者负责,调度引擎只负责顺序调度,从而实现了调度逻辑与策略逻辑的解耦。 但受制于当时的硬件和语言特性,这一代调度主要是单线程串行执行,对多核 CPU 的利用率极低。随着硬件演进和业务规模增长,这种调度方式逐渐暴露出瓶颈。 第一代策略调度引擎一般没有统一的标准,即使在一个系统中,每个微服务内部都有各自不同的调度框架。配置的方式,调度的方式也各有差别。以广告系统为例,一个典型的高级排序服务内部流程如下: graph TD A[解析请求参数] --> B[获取特征] B --> C[广告触发/基础位索引] C --> D[广告排序] D --> E[获取物料] E --> F[返回结果] 类结构如下: classDiagram class Strategy { <<interface>> } class Scheduler class ParserStrategy class SearchStrategy Scheduler ..> Strategy : Use Strategy <|-- ParserStrategy : Extends Strategy <|-- SearchStrategy : Extends Strategy <|-- OtherStrategies : Extends class OtherStrategies 框架通过Strategy设计模式,实现了逻辑上的抽象和隔离。策略算子的调度以顺序执行为主,并行计算很少。 ...

October 2, 2025 · Skyan

llama2.c 源码阅读

1. 概述 前OpenAI著名工程师Andrej Kapathy开源了llama2.c项目,该项目是llama2模型推理代码的C语言实现,用大概970行C代码实现了LLama2模型的推理算法。整个项目代码简洁高效,值得深度阅读。对掌握大模型推理算法的细节有极大的帮助。 2. 源码阅读 2.1 基础算法 RMS归一化公式是: $$ o_i = w_i \times x_i \times \frac {1}{\sqrt{\frac{1}{n}\sum_{j=0}^{n-1} x_j^2 + \epsilon}} $$ 其中,\(\epsilon\) 为防止分母为0的数值。还有RMS因子是对x的归一化,w变量是gain变量,重新缩放标准化后的输入向量。 // ---------------------------------------------------------------------------- // neural net blocks; the dynamics of the Transformer void rmsnorm(float* o, float* x, float* weight, int size) { // calculate sum of squares float ss = 0.0f; for (int j = 0; j < size; j++) { ss += x[j] * x[j]; } ss /= size; ss += 1e-5f; ss = 1.0f / sqrtf(ss); // normalize and scale for (int j = 0; j < size; j++) { o[j] = weight[j] * (ss * x[j]); } } softmax函数公式是: $$ o_i = \frac {e^{x_i-x_{max}}}{\sum_{j=0}^{n-1} e^{x_j-x_{max}}} $$代码如下,注释说的很清楚,减去最大值是为了防止数值溢出,数值更稳定。通过简单数学变换可以得知,最终结果不变。 void softmax(float* x, int size) { // find max value (for numerical stability) float max_val = x[0]; for (int i = 1; i < size; i++) { if (x[i] > max_val) { max_val = x[i]; } } // exp and sum float sum = 0.0f; for (int i = 0; i < size; i++) { x[i] = expf(x[i] - max_val); sum += x[i]; } // normalize for (int i = 0; i < size; i++) { x[i] /= sum; } } W (d,n) @ x (n,) -> xout (d,)的矩阵乘法,采用naive的矩阵乘法,即外层循环是行,内层循环是列。代码如下: ...

July 6, 2024 · Skyan

Google abseil开源项目介绍

Google abseil是Google开源的优秀C++基础库,持续维护并且持续迭代。该库的代码质量和工程化水平属于业界顶级,值得我们在实际生产中使用和学习。不仅要善于使用abseil库,还要多看abseil的文档和代码,从中学习Google业界领先的C++经验。 这里先介绍几个abseil库的经典组件: 容器 Recommendation Prefer absl::flat_hash_map or absl::flat_hash_set in most new code (see above). Use absl::node_hash_map or absl::node_hash_set when pointer stability of both keys and values is required (rare), or for code migrations from other containers with this property. Note: Do not use popularity as a guide. You will see the “node” containers used a lot, but only because it was safe to migrate code to them from other containers. ...

June 1, 2023 · Skyan

FlameGraph火焰图原理

FlameGraph是世界知名计算机性能优化专家Brendan Gregg发明的一种性能数据可视化方法。通过不同色块可交互的展示,可动态展示系统运行时的性能热点。FlameGraph如下图所示: 按照作者介绍,FlameGraph可以用于分析CPU耗时,内存分配,非CPU耗时(线程等待,调度性能),混合运行时(CPU和非CPU运行混合),以及性能对比这5种性能分析的可视化。我们常用FlameGraph生成CPU耗时分析图,用来找到服务运行性能的热点,并专项优化以节省资源成本。其实,FlameGraph也有一套标准数据格式,根据这个格式,可以在任何适合的场景中生成所需要的FlameGraph,并可视化可交互地展示和分析。 FlameGraph适合用于有调用栈的数据可视化,通过一种类似柱子的布局,加上暖色调的颜色,很像火焰一样的图案,所以被称为火焰图。以大家常用的CPU耗时火焰图为例,它的组成元素如下: 一个函数调用栈用一列方框组成,每个方框代表一个函数 y轴代表函数调用的深度,从底向上逐层递进调用,最顶端的函数代表性能采集时刻正在运行的函数,下面是它的父函数,依次类推 x轴代表不同采集栈的集合。需要注意的是x轴并不代表时间顺序,同一层的函数按照字母序从左往右排列。这样如果两个同名函数在同一层,将会被合并成一个区块。 方框的宽度代表该函数在调用栈抽样中出现的次数,如果宽度越宽,代表这个函数在栈抽样中出现的越频繁,从CPU耗时的角度来说,也表示这个函数更耗时。 如果方框宽度足够则展示函数的全名,如果不够则展示部分或者不展示,鼠标放上去可以展示全名 每个方框的背景色其实并没有什么特别,其实就是选取了一组随机的暖色调。主要是为了方便眼睛能区分不同层的方框。 一个火焰图可以用于可视化单线程,多线程,多进程甚至多主机的性能数据。也可以为每个线程生成一份独立的火焰图用于更详细的分析。 方框的宽度不仅限于表示抽样次数,也可以表示其他指标。例如宽度可以表示线程阻塞的时长,这样的一个火焰图可以很清晰的看出哪些函数在阻塞线程,以及整个线程阻塞时函数的调用栈情况 以上即是一个火焰图静态的组成部分,更为有趣的是,Gregg也为火焰图增加了互动功能,使得用户体验更佳。 火焰图本身是一个SVG文件,配合Javascript,支持鼠标悬浮,点击放大,以及搜索功能: 鼠标悬浮:当鼠标光标放置到一个方框上方时,可以展示该方框的详细数据(函数名,采样次数,以及占比) 点击放大:当鼠标点击一个方框时,火焰图按照垂直方向放大,该方框以上的函数将被放大展示,其他部分浅色处理,方便聚焦一个函数的分析 搜索:可以用Ctrl/Command+F快捷键或者右上角搜索功能,按照函数名搜索。搜索到的函数会高亮显示,还是在右下角展示所有搜索到的函数出现次数占比 火焰图生成流程是怎样的呢?按照Gregg开源的flamegraph.pl程序,生成一个火焰图只需要3步: 从perf,dtrace,gperftools等程序中获取运行时的调用栈数据 转换为折叠栈格式(Fold stacks) 调用flamegraph.pl生成火焰图 原理非常简单。所以搞懂火焰图只需要明白折叠栈是怎么回事即可。首先一个函数的调用栈可能长这样: func_c func_b func_a start_thread clone func_d func_a start_thread clone func_d func_a start_thread clone 上面展示了三次性能抽样,每次抽样从底向上显示了一个调用栈,折叠栈格式如下: clone;start_thread;func_a;func_b;func_c 1 clone;start_thread;func_a;func_d 2 其实就是将三个栈做了一个汇总,将同样的栈汇总到一起,每个函数用’;‘分隔,最后加空格和打印出现次数。 前面还可以加上程序的名称,例如cpp,如下也是一个合法的folded stacks: cpp;clone;start_thread;func_a;func_b;func_c 1 cpp;clone;start_thread;func_a;func_d 2 有了折叠栈数据,即可利用flamegraph.pl生成对应的火焰图svg文件。该文件可以嵌入到任何网页中展示,简单方便。 进一步,我们可以利用火焰图原理,生成各种场景所需要的“火焰图”,用于性能分析,数据可视化展示等功能。我们以应用层算子调度框架的性能分析为例,展示如何利用火焰图生成算子耗时可视化图。 应用层算子调度框架常见于RPC服务端的应用层,主要思想是将策略逻辑封装成若干个函数式的算子,再通过调度框架,串行或者并行调度这些算子运行,最终产出RPC的返回结果。算子调度的拓扑图有叫Tree,也有叫DAG的,也有叫图的。下图所示就是一个典型的算子调度框架的运行时拓扑图。 针对这样的算子调度,经常需要分析的问题有:哪个算子耗时最高,最长路径在哪里,哪个算子可以优化调度路径等,我们通常通过打印日志和统计最长路径等方法来分析运行时性能情况。但同样,通过火焰图也可以将运行拓扑的耗时可视化起来。 生成火焰图的关键即为生成栈的汇总数据,假设每个算子的耗时情况如下: 运行阶段 解析请求 访问A服务 访问B服务 汇总结果 产生返回数据 开始运行时间 0 10 10 24 32 结束运行时间 10 20 24 32 34 我们想象有一个抽样程序,可以按照上面的运行时图,从左往右分别垂直抽样,可以看出在不同时间段有这样几种“栈”: ...

December 5, 2022 · Skyan