首页/新闻资讯/正文详情

Dart SDK vm_service_protos:Perfetto 跟踪解码包的版本演进与字符串驻留(Interning)API 深度解析

发布时间:2026/9/25 6:03:18 来源:云帆数科 栏目:资讯中心
Dart SDK vm_service_protos:Perfetto 跟踪解码包的版本演进与字符串驻留(Interning)API 深度解析
编程语言编译器语言运行时标准库开发工具【免费下载链接】sdkThe Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.项目地址https://gitcode.com/gh_mirrors/sdk1/sdk点击查看免费下载本文以 Dart SDK 仓库中 pkg/vm_service_protos/CHANGELOG.md 记录的版本历史为主线,结合包内源码、第三方 Perfetto proto 定义与 VM 服务协议的测试用例,完整梳理vm_service_protos包从 1.0.0 到 2.0.1 的每次 API 变更。读完本文,你将理解该包在 Dart VM 服务协议中的定位、2.0.0 围绕字符串驻留机制新增的全部类与访问器、Perfetto 驻留索引(interning index)的工作原理,以及读者端(reader-side)如何配合InternedData还原跟踪事件名称的官方实践。vm_service_protos 是什么按包 README 的定义,vm_service_protos是 A library for decoding protos returned by a service implementing the Dart VM service protocol——一个用于解码实现 Dart VM 服务协议的服务所返回的 protobuf 消息的库。VM 在提供 Perfetto 格式的时间线/CPU 采样数据时,输出的是 Perfetto 跟踪格式的 protobuf 字节流;vm_service_protos就是把这些字节流转译为类型化 Dart 对象(TracePacket、TrackEvent、InternedData等)的生成代码包。从 pubspec.yaml 可以看到当前包的工程事实:version: 2.0.1,与 CHANGELOG 顶层条目一致;environment: sdk: ^3.5.0,即要求 Dart 3.5 及以上;resolution: workspace,说明它是 SDK 仓库 pub workspace 的组成部分,版本约束直接来自仓库的 DEPS 文件(pubspec 中的注释专门解释了这是特殊情形,与一般包应写明兼容版本区间的良好实践不同);运行时依赖只有两个:fixnum: ^1.0.0与protobuf: ^6.0.0,dev 依赖为lints: any。公开入口是 lib/vm_service_protos.dart,它只由export语句组成,一次性暴露 35 个生成文件,覆盖 Perfetto 跟踪体系中的核心消息族:builtin_clock、clock_snapshot、trace、trace_packet、interned_data、profile_common、profile_packet,以及track_event目录下的debug_annotation、process_descriptor、thread_descriptor、track_descriptor、track_event等。这正是 1.0.0 版本日志中 code for working with Perfetto protos, which can be imported frompackage:vm_service_protos/vm_service_protos.dart 所指的导入路径。版本历史:逐条解读 CHANGELOG1.0.0 —— 初始版本CHANGELOG 记录 1.0.0 仅有一条实质内容:Initial version 加上Add code for working with Perfetto protos, which can be imported frompackage:vm_service_protos/vm_service_protos.dart。即 1.0.0 交付的是一套可解码 VM 服务协议返回的 Perfetto 消息的生成代码,入口统一收敛在 vm_service_protos.dart。从仓库结构看,该版本对应的就是当前lib/src/protos/perfetto/下的消息族,只是尚未包含 2.0.0 引入的驻留相关访问器。2.0.0 —— 以驻留机制为核心的 API 大幅扩充2.0.0 是功能大版本,CHANGELOG 逐条记录了以下变更,全部可在当前生成代码中得到印证:提升package:protobuf依赖约束到 4.0.0。当前仓库 pubspec 中该约束已演进为protobuf: ^6.0.0(见上节),2.0.0 时点则以 4.0.0为下限;引入EventCategory、EventName、DebugAnnotationName三个类。它们是驻留字典的条目类型,定义在 track_event.pb.dart 与 debug_annotation.pb.dart 中,并被 InternedData 的工厂构造器作为eventCategories、eventNames、debugAnnotationNames三个Iterable参数接收;为InternedData增加eventCategories、eventNames、debugAnnotationNames、debugAnnotationStringValues四个 getter。对照 interned_data.pb.dart 的BuilderInfo注册,这些字段编号分别为 1、2、3 和 29,与 interned_data.proto 中的repeated字段一一对应(proto 中Next id: 29的注释正对应debugAnnotationStringValues这一新增字段);为DebugAnnotation增加nameIid与stringValueIid两个 getter,以及hasNameIid、clearNameIid、hasStringValueIid、clearStringValueIid四个方法。has/clear方法是 protobuf 生成的标准字段是否设置/清空配套,供读者端判断一个注解名或字符串值是内联存储还是驻留引用;为TrackEvent增加categoryIids与nameIid两个 getter,以及hasNameIid、clearNameIid两个方法。这让事件可以直接携带类别驻留 ID 列表与名称驻留 ID,而不必内嵌重复的字符串。这一组变更的共同目的,是支持 Perfetto 的字符串驻留(interning)写入模式:写入端(writer)不再把每个跟踪事件的名称字符串重复序列化,而是把新字符串登记到InternedData字典中,后续事件只引用字典位置的整数 ID(interning ID,缩写 iid)。对解码方而言,2.0.0 之前拿不到这些 iid 字段,也就无法还原驻留写入的数据——这正是 2.0.0 大版本升级的原因。2.0.1 —— 兼容 protobuf 5.0 系列的维护版本2.0.1 在 CHANGELOG 中只有一条:Include support forpackage:protobuf5.0,即为package:protobuf5.x 系列保持/纳入兼容性,属于不改变公共 API 的维护性发布。需要说明的适用前提是:仓库当前检出的 pubspec.yaml 已将protobuf固定为^6.0.0且要求 Dart SDK^3.5.0,这是面向后续版本的开发态配置;2.0.1 所声明的兼容范围以该版本发布时的依赖解析为准。2.0.0 API 背后的原理:Perfetto 驻留索引如何工作要理解上面那批 getter 和类的必要性,需要读一下 proto 定义。interned_data.proto 文件头部的注释(第 33~50 行)系统解释了驻留机制:驻留索引是按包序列(packet sequence,即同一 producer/TraceWriter 产出的TracePacket链)逐步构建的,包只能引用同一序列内的驻留数据;写入端遇到字典中尚不存在的新值时,就追加一个新条目;当前及后续的包用该条目在字典中的位置(iid)来引用它,iid 取 0 表示无效(未设置);由于索引是增量构建的,若中间TracePacket丢失(例如环形缓冲区中某块数据被覆盖),索引就会缺失数据。为避免整个跟踪因此作废,索引会被周期性重置——对应的控制位就是SEQ_INCREMENTAL_STATE_CLEARED序列标志。生成的 Dart 侧 InternedData 完整承载了这张字典:除 2.0.0 新增的四个 getter 对应的字段外,还包括面向 CPU 采样剖析的functionNames(字段 5)、frames(6)、callstacks(7)、buildIds(16)、mappingPaths(17)、mappings(19)。其工厂构造器接受这些字段的Iterable参数并逐个addAll,体现了 protobuf 生成代码repeated 字段 Dart 集合视图的一贯风格。实战:读取端如何用新 API 还原驻留字符串包 README 明确指引读者到两个测试学习 API 用法:get_perfetto_vm_timeline_rpc_test 与 get_perfetto_cpu_samples_rpc_test。时间线测试完整展示了 2.0.0 全部新 API 的协作方式,值得精读:VM 侧开关。测试文件头部的VMOptions--intern_strings_when_writing_perfetto_timeline(第 5~6 行)表明,VM 需要该选项才会以驻留模式写出时间线;测试据此判断stringsShouldBeInterned并切换断言逻辑;字典维护(Deinterner.update)。测试中自定义的Deinterner类在 第 29~57 行 对每个TracePacket先检查packet.sequenceFlags TracePacket_SequenceFlags.SEQ_INCREMENTAL_STATE_CLEARED:命中则清空四张 iid→字符串映射(debugAnnotationNames、debugAnnotationStringValues、eventNames、eventCategories),随后若packet.hasInternedData()成立,就把internedData里各条目的iid.toInt()作为键登记——这正是 proto 注释所述周期性重置语义在读者端的实现;事件还原(Deinterner.deintern)。第 60~90 行 处理单个TrackEvent:若event.hasNameIid()为真,则用eventNames[event.nameIid.toInt()]回填event.name并event.clearNameIid();若event.categoryIids非空,则逐 iid 查eventCategories映射后写回event.categories;对debugAnnotations中的每个DebugAnnotation同样以stringValueIid/stringValueIid完成还原。断言还验证了互斥不变量:驻留模式下hasNameIid()成立时hasName()必为假——这恰好是 2.0.0 在TrackEvent/DebugAnnotation上补充has*/clear*方法所服务的判断场景。从该测试的结构可以推断,任何自建 Perfetto 数据消费方(性能工具、DevTools 类前端)都应采用同样的包级字典 iid 查表还原模式,且必须处理SEQ_INCREMENTAL_STATE_CLEARED重置,否则在包丢失场景下会读到过期字典项。生成管线:proto 如何变成包内 Dart 代码vm_service_protos内所有.pb.dart均为生成文件,文件头(以 interned_data.pb.dart 第 5~11 行 为例)统一声明:This file should only ever be modified by modifying the corresponding .proto file and then runningdart third_party/perfetto/tools/compile_perfetto_protos.dartfrom the SDK root directory。完整的再生成流程在 third_party/perfetto/README.md 中说明:由于 Perfetto 的protozero_plugin(protoc 插件)不以二进制分发,需先从 Perfetto 源码树 out-of-tree 构建(README 给出了gn args/ninja -C out/linux protoc protozero_plugin的步骤,且需将 Perfetto 检出到本仓库 DEPS 文件指定的 revision);然后设置PATH指向构建产物并运行dart third_party/perfetto/tools/compile_perfetto_protos.dart,一次性生成 C 侧.pbzero.{cc,h}与 Dart 侧.pb.dart/.pbenum.dart/.pbjson.dart。该 README 还解释了仓库中 proto 为何是手工裁剪版(interned_data.proto 第 17~18 行的注释也写明 This is a manually minified version of Perfettos interned_data.proto):C 侧使用 header-only 的 protozero,裁剪与否对 VM 代码体积几乎无影响;但 Dart 侧不同,若采用 Perfetto 原版完整消息定义,会把大量消费方(如 DevTools)根本用不到的生成代码打进包中,而每个消息与其子消息强关联、默认无法被 tree-shake。因此仓库选择人工裁剪的最小 proto 集,这也决定了 2.0.0 新增的EventCategory/EventName/DebugAnnotationName等类型只包含 VM 实际用到的字段。此外,proto 头部注释要求对 proto 的任何改动都必须重新生成对应的.pbzero.h,因为 VM 的 C 序列化端(如 builtin_clock.pbzero.h 等)与 Dart 解码端必须共享同一份消息定义,两端字段编号必须严格一致——这也是 interned_data.proto 与 interned_data.pb.dart 中字段编号(1/2/3/5/6/7/16/17/19/29)完全吻合的原因。小结与参考路径vm_service_protos的版本史很短但每步都有明确动机:1.0.0 建立 Perfetto 解码能力,2.0.0 补齐字符串驻留的完整读取面(三个驻留条目类、InternedData四个字典 getter、DebugAnnotation/TrackEvent的 iid getter 与 has/clear 方法,并提升 protobuf 依赖下限),2.0.1 则维护对 protobuf 5.x 系列的兼容。当前仓库检出的 2.0.1 版本配套 Dart SDK^3.5.0与protobuf ^6.0.0约束,且属于 SDK pub workspace。继续深入时可查阅:版本日志:pkg/vm_service_protos/CHANGELOG.md包说明与用法指引:pkg/vm_service_protos/README.md、pkg/vm_service_protos/pubspec.yaml公开导出:pkg/vm_service_protos/lib/vm_service_protos.dart驻留字典 proto 与生成代码:third_party/perfetto/protos/perfetto/trace/interned_data/interned_data.proto、pkg/vm_service_protos/lib/src/protos/perfetto/trace/interned_data/interned_data.pb.dartproto 裁剪动机与再生成流程:third_party/perfetto/README.md、third_party/perfetto/tools/compile_perfetto_protos.dart官方用法示例(时间线与 CPU 采样解码):pkg/vm_service/test/get_perfetto_vm_timeline_rpc_test.dart、pkg/vm_service/test/get_perfetto_cpu_samples_rpc_test.dart赞分享编程语言编译器语言运行时标准库开发工具【免费下载链接】sdkThe Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.项目地址https://gitcode.com/gh_mirrors/sdk1/sdk点击查看免费下载相关推荐Dart SDK 中 analysis_server_plugin 包的版本演进与插件机制深度解析Dart SDK 中 analysis_server_plugin 包的版本演进与插件机制深度解析 analysis_server_plugin 是 Dart编程语言编译器语言运行时标准库开发工具PHP 引擎的 zend_string 深度解析结构布局、API 与字符串驻留机制PHP 引擎的 zend_string 深度解析结构布局、API 与字符串驻留机制 PHP 解释器php src中所有字符串——变量值、数组键、类名、属性编程语言语言运行时解释器wtfpython源码解读深入理解CPython的字符串驻留机制wtfpython源码解读深入理解CPython的字符串驻留机制 引言Python字符串的诡异行为 你是否曾经遇到过这样的Python代码行为 pyt文档教程上一篇BindingX革命性跨平台动作绑定引擎轻松实现流畅交互体验下一篇KMS_VL_ALL_AIO使用指南轻松管理Windows和Office授权创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关推荐

OpenShell 沙箱代理出口适配器模型:EgressIntent 与 EgressDecision 技术设计详解
OpenShell 沙箱代理出口适配器模型:EgressIntent 与 EgressDecision 技术设计详解

【免费下载链接】OpenShell OpenShell is the safe, private runtime for autonomous AI agents. 项目地址: https://gitcode.com/gh_mirrors/op/OpenShell 点击查看 免费下载 本文基于 OpenShell 仓库中 RFC 0005 的技术设计附录 technical-design.md,… · 2026/9/25 6:03:18

使用 AWS SDK for JavaScript (v3) 操作 AWS Support:从工单创建到解决的完整实战指南
使用 AWS SDK for JavaScript (v3) 操作 AWS Support:从工单创建到解决的完整实战指南

示例工程教程后端 【免费下载链接】aws-doc-sdk-examples Welcome to the AWS Code Examples Repository. This repo contains code examples used in the AWS documentation, AWS SDK Developer Guides, and more. For more information, see the Readme.md file below. 项目地… · 2026/9/25 6:03:18

Atlas 300V Pro 24G实战:从驱动安装到YOLO模型转换与推理部署
Atlas 300V Pro 24G实战:从驱动安装到YOLO模型转换与推理部署

最近后台好几个朋友都在问同一个问题:Atlas 300V 24G到底是不是运算加速卡?能跑YOLO吗?正好我手头这张Atlas 300V Pro 24G已经用了一段时间,从装驱动、转模型到跑通YOLOv5/YOLOv8,能踩的坑基本都踩了一遍。这篇就把完整… · 2026/9/25 6:03:18

Windows下速腾激光雷达调试:RSVIEW点云可视化与Wireshark抓包排查
Windows下速腾激光雷达调试:RSVIEW点云可视化与Wireshark抓包排查

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 6:34:59

Atlas 300V 24G推理加速卡部署YOLO完整实战
Atlas 300V 24G推理加速卡部署YOLO完整实战

最近后台和评论区都在问同一个词:atlas。点进来一看,十有八九都是“atlas部署yolo”和“atlas 300v 24g 是运算加速卡吗”这两条。作为一个在推理加速卡上跑过不少目标检测模型的从业者,我直接给结论:Atlas 300V 24G 算不算运算加… · 2026/9/25 6:34:52

ax:基于Kubernetes的Agentic任务调度编排CLI实践
ax:基于Kubernetes的Agentic任务调度编排CLI实践

1. 从“ax”这个标题说起:一个被低估的Agentic调度入口第一次看到“ax”这个标题,很多人会以为是某个命令行工具的缩写,或者某个内部项目的代号。但把热搜词摊开来看——ax、agentic、orchestrator、Kubernetes、CLI——这几个词凑在一起&… · 2026/9/25 6:34:46

Keil MDK升级与STM32F4xx_DFP安装避坑指南
Keil MDK升级与STM32F4xx_DFP安装避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 6:34:46

RK3128老盒子焕新记:通刷固件+系统优化实战
RK3128老盒子焕新记:通刷固件+系统优化实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 6:34:40

MIPS单周期CPU设计指南:从指令集、数据通路到Verilog仿真上板
MIPS单周期CPU设计指南:从指令集、数据通路到Verilog仿真上板

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 6:34:40

数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)
数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31

创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31

MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码