图形学图像处理【免费下载链接】skiaSkia is a complete 2D graphic library for drawing Text, Geometries, and Images.项目地址https://gitcode.com/gh_mirrors/skia1/skia点击查看免费下载导读本文以 Skia 官方开发文档 site/docs/dev/tools/tracing.md 为骨架结合本仓库源码tools/trace/下的四个 Tracer 实现、src/core/SkTraceEvent.h、include/utils/SkEventTracer.h展开系统讲解 Skia 在 Chrome、Android framework 与独立构建三种场景下的执行追踪Tracing机制。你将掌握--trace命令行参数的四种取值JSON 文件、atrace、debugf、perfetto的用法与适用场景Perfetto 追踪的全部运行时选项输出路径、长追踪、按 Benchmark 拆分等以及如何用TRACE_EVENT*宏在源码中新增埋点从而独立完成 Skia 工具DM、nanobench、Viewer的性能剖析与调试。一、Skia 追踪的整体架构Skia 提供了多层次的执行追踪能力覆盖从宿主平台到独立构建工具的不同场景Chrome 内Skia 与 Chromium 其余部分一起通过标准的 chrome://tracing 追踪接口输出事件。Android framework 内Skia 的追踪被集成进 Android 的 atrace 与 src/core/SkATrace.h。独立构建standalone buildsSkia 自带的三大工具 DM、nanobench、Viewer 均可通过统一的--trace命令行参数在以下三种/四种模式间切换任意其他字符串被解释为文件名将追踪事件以 JSON 格式写入该文件供 chrome://tracing 加载查看atrace——将事件转发给 Android 的 atrace仅 Android 有效debugf——通过SkDebugf将事件直接打到控制台perfetto——将事件转发给 Perfetto仅 Linux、Mac、Android 有效。从源码结构看这一切的枢纽是--trace标志的解析与分发。在 tools/trace/EventTracingPriv.cpp 中DEFINE_string(trace, ...)定义了该参数initializeEventTracingForTools()按字符串取值选择对应的SkEventTracer实现static DEFINE_string(trace, , Log trace events in one of several modes:\n debugf : Show events using SkDebugf\n atrace : Send events to Android ATrace\n perfetto : Send events to Perfetto (Linux, Android, and Mac only)\n filename : Any other string is interpreted as a filename. Writes\n trace events to specified file as JSON, for viewing\n with chrome://tracing); void initializeEventTracingForTools(const char* traceFlag) { ... SkEventTracer* eventTracer nullptr; if (0 strcmp(traceFlag, atrace)) { eventTracer new SkATrace(); } else if (0 strcmp(traceFlag, debugf)) { eventTracer new SkDebugfTracer(); } else if (0 strcmp(traceFlag, perfetto)) { #if defined(SK_USE_PERFETTO) eventTracer new SkPerfettoTrace(); #else SkDebugf(Perfetto is not enabled (SK_USE_PERFETTO is false). ...); return; #endif } else { eventTracer new ChromeTracingTracer(traceFlag); } SkAssertResult(SkEventTracer::SetInstance(eventTracer)); }SkEventTracer是 Skia 内部追踪宏与外部消费方之间的接口定义在 include/utils/SkEventTracer.h外部实体如 Chrome、Perfetto通过继承SkEventTracer并调用SkEventTracer::SetInstance()注册实例Skia 内部的TRACE_EVENT宏则调用其虚方法上报事件。独立工具模式下这个实例就是上面四种 Tracer 之一。二、独立构建模式JSON 文件输出与 chrome://tracing 可视化--trace的大多数取值都被当作文件名处理两个例外是debugf与atraceperfetto也属于关键字而非文件名事件会以 JSON 格式写入该文件供 chrome://tracing 加载查看# 在若干 GMs 上运行 DM 以采集追踪数据 out/Release/dm --config gl --match bleed --trace gl_bleed_gms.json该命令会在当前目录生成gl_bleed_gms.json。chrome://tracing 无法加载超过256 MB的文件因此建议在追踪时只运行少量测试/基准既控制文件体积也避免界面卡顿与信息过载。文件生成后打开 chrome://tracing点击 Load选择 JSON 文件后即可用追踪工具导航和检视数据。提示按?键可查看鼠标/键盘控制快捷键的帮助界面。JSON 输出的实现细节负责 JSON 输出的ChromeTracingTracer位于 tools/trace/ChromeTracingTracer.cpp事件先在内存中按固定大小的块block累积块满后推入fBlocks队列appendEvent最终由flush()一次性写出。TraceEvent结构体ChromeTracingTracer.cpp保存事件阶段phase、名称、起止时钟、线程 ID 与可变长参数事件参数紧跟在事件头之后字符串被复制进内部 string table。序列化为 JSON 时trace_event_to_json时间戳统一减去首个事件的时间以缩短 JSON 长度并把纳秒换算成微秒ts/dur字段线程 ID 被压缩为从 0 开始的短 ID进程 ID 固定为 0。参数支持布尔、整数、浮点、指针、字符串与拷贝字符串六种类型。flush()会先用SkJSONWriter写出一个 JSON 数组ChromeTracingTracer.cpp若目标目录不存在还会自动创建。整个实现采用单锁保护块式累积对高频小事件有不错的性能。三、Android ATrace把事件转发到系统追踪在任何 Android 设备上运行带--trace atrace的工具应用会把追踪信息转发给 atrace在非 Android 平台上该参数无效果。需要特别注意的是systrace的-a app_name参数app_name必须与目标设备上实际使用的命令行完全一致。例如adb shell cd /data/local/tmp; ./nanobench --trace atrace ...宿主侧必须传-a ./nanobench否则 systrace 会忽略该应用发来的事件。从源码看SkATracesrc/core/SkATrace.cpp、src/core/SkATrace.h是一个独立的SkEventTracer实现事件通过 Android 的 ATrace APIATrace_beginSection/ATrace_endSection等写入系统 ftrace 缓冲区从而与系统层追踪CPU 调度、内存、Binder 等在时间轴上对齐便于分析 Skia 绘制与系统负载的耦合关系。四、Console Logging用 SkDebugf 快速定位对于简单场景--trace debugf可以把所有追踪事件直接输出到控制台# 在单个 GM 上运行 DM 并使用 SkDebugf 追踪 out/Release/dm --config gl --match ^gamma$ --trace debugf输出示例原文档[ 0] skia.gpu GrDrawingManager::internalFlush id1 #0 { [ 0] } GrDrawingManager::internalFlush [ 0] skia.gpu GrGpu::createTexture id1 #1 { [ 0] } GrGpu::createTexture [ 0] skia.gpu GrRenderTargetContext::discard id1 #2 { [ 0] } GrRenderTargetContext::discard [ 0] skia.gpu SkGpuDevice::clearAll id1 #3 { [ 1] skia.gpu GrRenderTargetContext::clear id1 #4 { [ 1] } GrRenderTargetContext::clear [ 0] } SkGpuDevice::clearAll [ 0] skia SkCanvas::drawRect() #5 { [ 1] skia.gpu SkGpuDevice::drawRect id1 #6 { [ 2] skia.gpu GrRenderTargetContext::drawRect id1 #7 { [ 3] skia.gpu GrRenderTargetContext::addDrawOp id1 #8 { [ 3] } GrRenderTargetContext::addDrawOp [ 2] } GrRenderTargetContext::drawRect [ 1] } SkGpuDevice::drawRect [ 0] } SkCanvas::drawRect() ...输出中每一行的含义方括号内是嵌套深度缩进与之对应{表示事件开始、}表示事件结束一眼即可看出调用层级category是事件分类如skia、skia.gpu可用于过滤#N是全局递增的事件编号方便对齐讨论参数会以namevalue形式附加字符串值会被截断到 20 个字符并在换行处截断见 SkDebugfTracer.cpp。SkDebugfTracer的实现位于 tools/trace/SkDebugfTracer.cppCOMPLETE 阶段事件输出[深度] 分类 名称 #N {并增加一级缩进结束时输出[深度] } 名称newTracingSection()则打印- - - New tracing section: name - - -分隔符。它是排查“某个函数是否被调用、调用顺序如何”最轻量的手段。五、Tracing with Perfetto现代追踪方案与完整运行时配置运行任何工具时使用--trace perfetto应用会把追踪信息转发给 Perfetto。Perfetto 仅支持Linux、Mac 和 Android其他平台不会运行。5.1 短追踪与长追踪的取舍默认情况下Skia 内的 Perfetto 追踪被配置为处理相对较短约 10 秒以内的追踪事件与会话例如只跑一部分测试而非整个测试套件。任何长于约 10 秒的追踪会话都推荐使用--longPerfettoTrace运行时选项——它会改变 Skia 的 Perfetto 配置以适配更长追踪否则长追踪可能覆盖已有事件导致数据丢失。从 tools/trace/SkPerfettoTrace.cpp 的源码可以看到短/长两种配置的具体差异短追踪共享内存缓冲区使用默认的 256 KB中央缓冲区add_buffers()-set_size_kb(32000)约 32 MB会话结束后一次性把整段数据读出写盘。长追踪--longPerfettoTrace置位后args.shmem_size_hint_kb 2000把共享内存提示提高到 2 MB降低写包丢失cfg.set_write_into_file(true)启用流式写盘追踪期间持续落盘而非结束时一次性 dumpcfg.set_file_write_period_ms(5000)每 5 秒写一次文件cfg.set_flush_period_ms(10000)每 10 秒强制提交共享内存页到中央缓冲区防止长追踪出现乱序事件切片。同时SkPerfettoTrace只启用了perfetto::kInProcessBackend进程内记录并不依赖 Perfetto 守护进程SkPerfettoTrace.cpp。5.2 输出文件路径的运行时参数追踪输出路径可由运行时参数定制参数作用默认值--perfettoOutputDir输出目录注意不是文件名本身./当前目录--perfettoOutputFileName输出文件名不含路径与扩展名与--splitPerfettoTracesByBenchmark配合时由 Benchmark 名决定trace--perfettoOutputFileExtension输出文件扩展名.perfetto-trace默认情况下追踪文件会被放在构建输出目录中命名为trace.perfetto-trace即./trace.perfetto-trace。三个参数的默认值与解析见 SkPerfettoTrace.cpp。5.3 按 Benchmark 拆分追踪文件如果希望为 nanobench 的每个基准测试单独生成一个追踪文件可使用--splitPerfettoTracesByBenchmark开启后输出文件将以各 Benchmark 的名字命名。从源码看其机制是SkPerfettoTrace::newTracingSection()SkPerfettoTrace.cpp每个新追踪段先关闭上一会话、再以新基名打开会话fOutputPath与fOutputFileExtension被拆开存储正是为了在改名基名时保持路径与扩展名不变见 SkPerfettoTrace.h 的注释。5.4 可视化与问题排查生成的追踪文件可用 Perfetto 的网页可视化工具 查看。超过约2 GB的大型追踪文件参考 Perfetto 大追踪官方指引。遇到异常或不符合预期的结果时先看网页工具上的 “Info and stats” 页面或对追踪文件运行 SQL 查询在线或使用 trace processor 应用来定位根因诊断数据丢失参考 缓冲区数据丢失排查排查可能意外显长的乱序事件参考 flushes 与窗口化导入。5.5 编译前提--trace perfetto依赖构建时定义SK_USE_PERFETTO。在 EventTracingPriv.cpp 中SK_USE_PERFETTO与SK_ANDROID_FRAMEWORK_USE_PERFETTO互斥同时定义会触发#error未定义SK_USE_PERFETTO时--trace perfetto会打印 “Perfetto is not enabled” 提示并直接返回不会执行追踪。六、添加更多追踪事件TRACE_EVENT 宏为 Skia 源码增加新的追踪事件需要引入一组TRACE_宏。最简单的用法是记录某个函数或任意作用域内的耗时#include SkTraceEvent.h ... void doSomething() { // 为当前函数或其他作用域的持续时间添加一个事件 // skia 是分类名用于录制时过滤事件 // TRACE_FUNC 是事件名展开为当前函数名 TRACE_EVENT0(skia, TRACE_FUNC); if (doExtraWork) { TRACE_EVENT0(skia, ExtraWorkBeingDone); ... } }要点说明TRACE_EVENT0(skia, ...)中的skia是事件分类category录制时可用它过滤skia.gpu等子分类用于更细粒度的区分。TRACE_FUNC在 src/core/SkTraceEvent.h 中定义MSVC 下展开为__FUNCSIG__其他编译器下展开为__PRETTY_FUNCTION__即自动取当前函数名作为事件名。事件是作用域绑定的进入作用域记录开始离开作用域自动记录结束与持续时间底层由SkEventTracer::updateTraceEventDuration完成因此TRACE_EVENT0通常写在函数体开头。更丰富的宏与参数更多示例其他事件类型、给事件附加参数等请参见 SkTraceEventCommon.h 中的注释。常见能力包括事件阶段phase系统COMPLETE完整作用域事件、INSTANT瞬时事件、CREATE/DELETE/SNAPSHOT OBJECT对象生命周期快照Chrome 的 JSON 输出会据此自动补充base_name字段见 ChromeTracingTracer.cpp。参数类型BOOL、UINT、INT、DOUBLE、POINTER、STRING、COPY_STRING 七种三种 Tracer 各自实现了类型化输出JSON 见 ChromeTracingTracer.cppdebugf 见 SkDebugfTracer.cppPerfetto 见 SkPerfettoTrace.cpp。字符串参数默认假定const char*指向长生命周期内存而不拷贝短生命周期字符串用TRACE_STR_COPY(str)强制拷贝进程生命周期内的静态字符串用TRACE_STR_STATIC(str)宏定义见 src/core/SkTraceEvent.h。类别过滤--traceMatch除宏中的分类名外独立工具还支持--traceMatch标志过滤被追踪的分类其格式与--match相同见 EventTracingPriv.cpp。SkEventTracingCategories::getCategoryGroupEnabled()在注册新分类时依据CommandLineFlags::ShouldSkip(FLAGS_traceMatch, name)决定该分类是否启用EventTracingPriv.cpp分类表容量上限为 256kMaxCategories。七、总结如何选择正确的追踪模式模式适用场景平台限制产出filenameJSON深度性能分析、与 chrome://tracing 的完整交互检视无可加载的 JSON 追踪文件256 MBatrace分析 Android 上 Skia 与系统负载的时序耦合仅 Android系统 ftrace/systrace 数据debugf快速确认调用顺序与嵌套关系无控制台文本输出perfetto现代大容量追踪、流式写盘、按 Benchmark 拆分仅 Linux/Mac/Android需SK_USE_PERFETTO.perfetto-trace文件ui.perfetto.dev 可视化实操建议定位问题先用--trace debugf成本最低需要完整时间线做回归对比时用 JSON 模式并控制测试数量以避开 256 MB 上限Android 平台优先--trace atrace记得 systrace 的-a参数与设备端命令行完全一致超过 10 秒的 Perfetto 会话务必加--longPerfettoTrace并合理使用--perfettoOutputDir、--perfettoOutputFileName、--perfettoOutputFileExtension与--splitPerfettoTracesByBenchmark管理输出。需要给 Skia 内部加新埋点时在函数开头插入TRACE_EVENT0(skia, TRACE_FUNC)即可更多事件类型与参数写法参考 src/core/SkTraceEventCommon.h 的注释与 src/core/SkTraceEvent.h 的实现。赞分享图形学图像处理【免费下载链接】skiaSkia is a complete 2D graphic library for drawing Text, Geometries, and Images.项目地址https://gitcode.com/gh_mirrors/skia1/skia点击查看免费下载相关推荐Skia 执行追踪Tracing完全指南从 --trace 命令行到 TRACE_EVENT 插桩宏Skia 执行追踪Tracing完全指南从 trace 命令行到 TRACE_EVENT 插桩宏 本篇指南基于 Skia 官方文档 site/docs/d图形学洛雪音乐音源深度探索多平台聚合播放的技术解密洛雪音乐音源深度探索多平台聚合播放的技术解密 想要在洛雪音乐中畅享全网高品质音乐面对众多音源选择不知从何下手本文将为你揭秘洛雪音乐音源项目的核心技术从零音视频免费开源天气APIOpen-Meteo完全自主气象服务搭建指南免费开源天气APIOpen Meteo完全自主气象服务搭建指南 在数字化时代气象数据已成为众多应用的核心需求——从农业监测到出行规划从能源管理到灾害预警。后端API网关数据工程上一篇如何掌握AutoHotkey脚本依赖管理10个高效解决方案下一篇告别繁琐配置html-webpack-plugin打造Vue应用的单页与多页方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考