Compose Multiplatform 跨平台性能基准测试指南:模式、参数与运行脚本全解析

Compose Multiplatform 跨平台性能基准测试指南:模式、参数与运行脚本全解析 Compose Multiplatform 跨平台性能基准测试指南模式、参数与运行脚本全解析【免费下载链接】compose-multiplatformCompose Multiplatform, a modern UI framework for Kotlin that makes building performant and beautiful user interfaces easy and enjoyable.项目地址: https://gitcode.com/GitHub_Trending/co/compose-multiplatform本篇技术指南围绕 Compose Multiplatform 官方仓库中的 benchmarks/multiplatform 基准测试项目展开系统讲解其在 Desktop、iOS、macOS、WebKotlin/Wasm 与 Kotlin/JS等目标平台上的性能测量机制、四种执行模式SIMPLE、VSYNC_EMULATION、REAL、STARTUP的差异与适用场景、完整的配置参数体系以及三个.main.kts自动化脚本run_benchmarks、compare_benchmarks、find_degradation的实战用法。读者读完后将能够独立配置并运行跨平台基准测试、对比不同 Compose Multiplatform 版本之间的性能差异并依据源码级证据定位性能回退的具体版本。基准测试项目概览Compose Multiplatform 基准测试项目位于仓库的 benchmarks/multiplatform 目录其核心目标是对 Compose Multiplatform 在不同目标平台上的各类组件与特性进行量化性能测量覆盖范围包括动画如AnimatedVisibility的显隐切换动画懒加载布局LazyVerticalGrid、复杂LazyColumn文本渲染与排版大规模文本项的连续滚动排版视觉效果雪花、星星、火箭粒子等复合动画特效GPU 着色器多层渐变与混合模式的 Canvas 绘制项目采用 Gradle 多模块结构settings.gradle.kts由:benchmarks主模块与:compose-scene-api、:compose-scene-impl场景实现模块组成。其中:compose-scene-impl会根据当前 Compose Multiplatform 版本自动切换底层场景实现compose-scene-impl-1/2/3保证基准测试在不同版本下都能以正确的内部 API 运行这一点在版本管理与场景实现适配一节详述。所有基准测试代码均位于 benchmarks/src/commonMain/kotlin/benchmarks 下按功能域分目录组织且全部使用commonMain共享源码因此同一份基准测试代码可在所有目标平台上运行。Benchmark 模式详解基准测试支持四种执行模式它们决定了性能的测量方式与报告口径SIMPLE简单模式直接测量基础帧耗时不考虑 VSync 同步。适合快速检查原始渲染性能例如在持续滚动时粗看帧率是否达标。当未通过modes参数指定任何模式时SIMPLE 与 VSYNC_EMULATION 会作为默认模式启用。VSYNC_EMULATIONVSync 仿真模式模拟 VSync 行为估算丢帧情况并给出更贴近真实体验的 CPU/GPU 百分位指标。它不需要真实显示设备因此在无头headless环境中也能运行适合 CI 流水线中做回归检测。REAL真实模式在带真实 VSync 的真实场景中运行能给出用户可感知的最准确结果FPS、实际丢帧数。但存在两个局限其一如果某一帧耗时恰好落在预算之内可能捕捉不到性能回退其二要求设备具有真实显示器在无头设备上可能存在问题。STARTUP启动性能模式专门测量应用启动性能从进程启动到首帧乃至后续帧输出一系列细粒度时间指标指标含义timeToMain从进程启动到进入应用入口点的时间平台相关仅 JVM/Desktop 可用timeFromMainToFirstFrame从入口点到渲染出第一帧的时间timeOfFirstFrame第一帧本身的渲染耗时timeToNthFrame从第一帧到可配置的第 N 帧的时间默认 N30longestFrames启动过程中耗时最长的 N 帧默认 N3模式组合通过modes参数可以启用一个或多个模式模式间以逗号分隔modesSIMPLE,VSYNC_EMULATION,REAL,STARTUP多个模式可以组合执行例如modesSTARTUP,REAL会先测量启动指标再运行实时性能测量最终产出一份统一报告。值得注意的是从 run_benchmarks.main.kts 的源码可以看到脚本内部会检测modes参数中是否包含startup若包含则会自动将separateProcess默认置为true——因为启动性能测量需要进程级隔离才足够准确。配置参数完整说明基准测试的配置参数可以通过三种方式传入Gradle 任务参数-PrunArguments...推荐方式.main.kts脚本参数直接作为脚本命令行参数gradle.properties中的runArguments属性参数一览表参数说明示例modes逗号分隔的执行模式列表SIMPLE、VSYNC_EMULATION、REAL、STARTUPmodesREAL,STARTUPbenchmarks逗号分隔的待运行基准测试列表可在括号中指定问题规模benchmarksLazyGrid(100),AnimatedVisibilitydisabledBenchmarks逗号分隔的需要跳过的基准测试列表disabledBenchmarksHeavyShaderwarmupCount测量开始前的预热帧数warmupCount50frameCount每个基准测试的测量帧数frameCount500emptyScreenDelay预热与测量之间的延迟毫秒仅 REAL 模式生效emptyScreenDelay1000startupFrameCount启动模式下首帧之后要测量的帧数默认 30startupFrameCount50startupLongestFramesCount启动模式下要报告的耗时最长帧数默认 3startupLongestFramesCount5parallel是否启用并行渲染仅 iOS 生效paralleltruesaveStatsToCSV是否将结果保存为 CSV 文件saveStatsToCSVtruesaveStatsToJSON是否将结果保存为 JSON 文件saveStatsToJSONtrueversionInfo在报告中附加版本信息versionInfo1.2.3reportAtTheEnd所有基准测试完成后打印汇总报告仅 REAL 模式生效reportAtTheEndtruelistBenchmarks列出所有可用基准测试后退出listBenchmarkstruebenchmarks参数支持指定问题规模例如LazyGrid(100)表示以 100 个条目的规模运行 LazyGrid 基准。这一机制对应源码中不同基准测试的规模参数化设计详见下文基准测试源码解析。命令行用法示例./gradlew :benchmarks:run -PrunArgumentsbenchmarksLazyGrid modesREAL frameCount200该命令在 Desktop 平台上以 REAL 模式、测量 200 帧的配置运行LazyGrid基准测试。各平台运行方式DesktopDesktop 平台是上手最快的目标直接运行 Gradle 任务即可./gradlew :benchmarks:run这是基准测试的默认入口所有支持的运行参数均可通过-PrunArguments传递。iOS原生在 iOS 上运行有两种途径使用 Fleet 或安装了 KMM 插件的 Android Studio 打开项目选择iosApp运行配置务必在 Release 配置下构建应用在 Xcode 中打开iosApp/iosApp项目并直接运行。macOS原生根据处理器架构选择对应的 Gradle 任务./gradlew :benchmarks:runReleaseExecutableMacosArm64 # Arm64 处理器 ./gradlew :benchmarks:runReleaseExecutableMacosX64 # Intel 处理器WebKotlin/Wasm 与 Kotlin/JS在浏览器中运行前建议先以**手动 GCManual GC**模式启动浏览器以获得更干净的测量环境。以 Google Chrome 为例open -a Google\ Chrome --args --js-flags--expose-gcKotlin/Wasm./gradlew clean :benchmarks:wasmJsBrowserProductionRun结果直接打印在页面本身上Kotlin/JS./gradlew clean :benchmarks:jsBrowserProductionRun同样在页面打印结果Wasm 的 D8V8 引擎目标./gradlew :benchmarks:wasmJsD8ProductionRun可携带参数运行如./gradlew :benchmarks:wasmJsD8ProductionRun -PrunArgumentsbenchmarksAnimatedVisibility。如需构建 Jetstream3 风格的 Wasm D8 发行包并直接用 V8 二进制运行./gradlew :benchmarks:buildD8Distribution --rerun-tasks # 在发行包目录中执行路径仅为示例 ~/.gradle/d8/v8-mac-arm64-rel-11.9.85/d8 --module launcher_jetstream3.mjs -- AnimatedVisibility 1000查看可用基准测试运行listBenchmarkstrue可以列出项目内全部可用的基准测试名称脚本层run_benchmarks.main.kts正是通过解析AVAILABLE_BENCHMARKS_START与AVAILABLE_BENCHMARKS_END标记行来动态获取该列表用于separateProcesstrue时逐个进程分发执行。一键运行脚本run_benchmarks.main.ktsrun_benchmarks.main.kts 是跨平台运行基准测试的主入口脚本统一封装了 macos、desktop、web、ios源码中还包含 android四类平台。它处理了大量平台相关细节例如为 Web 基准测试启动后台服务器runServertrue、为 macOS 将构建产物重命名为带版本号的可执行文件、调用 iOS/Android 专属脚本等。用法与参数./run_benchmarks.main.kts platform [runs1] [benchmarksbenchmarkName] [versionversion] [separateProcesstrue|false] [any other gradle args]参数说明platform目标平台macos、desktop、web、iosrunsnumber迭代次数默认 1benchmarksname1,name2,...过滤要运行的基准测试versionversion指定 Compose Multiplatform 版本脚本会先改写gradle/libs.versions.toml再运行结束后自动还原separateProcesstrue每个基准测试在独立进程中运行隔离性更好默认false其他参数直接透传给基准测试执行例如modesSIMPLE示例./run_benchmarks.main.kts macos benchmarksLazyList runs3 version1.10.0该命令在 macOS 上以1.10.0版本连续运行 3 轮LazyList基准测试。从源码run_benchmarks.main.kts可以确认其版本管理逻辑脚本会在运行前读取并暂存gradle/libs.versions.toml通过正则替换compose-multiplatform版本号全部轮次结束后在finally块中恢复原文件内容避免污染仓库配置。结果归档每轮运行结束后JSON 结果会被归档到如下目录源码见 run_benchmarks.main.ktsbenchmarks/build/benchmarks/archive/${platform}/${version}_run${runIndex}脚本在归档前会先清理benchmarks/build/benchmarks/json-reports目录中上一轮的 JSON 文件防止旧结果被误归档进新轮次。版本对比脚本compare_benchmarks.main.ktscompare_benchmarks.main.kts 用于对比两个 Compose Multiplatform 版本的基准测试结果是性能回归分析的基础工具。./compare_benchmarks.main.kts v1version1 v2version2 [runs3] [platformmacos|desktop|web|ios] [benchmarksname] [skipExistingtrue] [separateProcesstrue]示例./compare_benchmarks.main.kts v11.9.0 v21.10.0 runs3 platformmacos skipExistingtrue参数说明v1/v2待对比的两个版本号runs每个版本的运行轮数默认 3platform目标平台benchmarks仅对比指定基准测试skipExistingtrue跳过已经归档过结果的版本节省重复运行时间separateProcesstrue每个基准测试独立进程运行。回归定位脚本find_degradation.main.ktsfind_degradation.main.kts 在版本列表上执行二分搜索定位首个引入性能回退定义为耗时增幅 5%的版本。./find_degradation.main.kts benchmarksbenchmarkName versionsversionsFile [platformmacos|desktop|web] [skipExistingtrue]其中versionsFile是一个纯文本文件每行一个版本号且必须按从旧到新的顺序排列。该脚本的核心价值在于当发现某一指标从版本 A 到版本 B 明显劣化后可以自动在 A 与 B 之间的所有历史版本中进行二分查找精确定位回退由哪个版本引入为代码评审和 bug 追踪提供明确的范围。iOS 专属脚本针对 iOS 平台仓库提供了两套运行工具.main.kts脚本./run_ios_benchmarks.main.kts DEVICE ID支持与其它目标平台完全一致的参数配置方式脚本参数或gradle.properties中的runArguments属性Shell 脚本iosApp/run_ios_benchmarks.shDEVICE ID专门支持real模式下多次尝试运行的场景。准备步骤若要在真机运行先打开iosApp/iosApp.xcodeproj在Signing Capabilities项目页签中正确配置签名Signing部分使用xcrun xctrace list devices获取全部 iOS 设备 ID 列表。常用命令# 从 benchmarks 目录运行指定设备上的全部基准测试 ./run_ios_benchmarks.main.kts DEVICE ID # 只运行指定的基准测试 ./run_ios_benchmarks.main.kts DEVICE ID benchmarksAnimatedVisibility,LazyGrid # 每个基准测试独立进程运行较慢但更可靠避免同进程内相互干扰 ./run_ios_benchmarks.main.kts DEVICE ID separateProcesstrue结果输出位置使用.main.kts脚本结果保存于benchmarks/build/benchmarks/text-reports/使用.sh脚本结果保存于benchmarks_result/。内置基准测试与源码解析项目内置了 9 组基准测试全部位于 benchmarks/src/commonMain/kotlin/benchmarks共享同一份commonMain代码因此测试场景在任何平台完全一致保证了跨平台对比的可信度。基准测试名称源码文件测试内容AnimatedVisibilityanimation/AnimatedVisibility.kt反复切换 PNG 图片的可见性测试AnimatedVisibility组件性能LazyGridlazygrid/LazyGrid.kt12000 条目的LazyVerticalGrid运行中多次跳转到指定条目LazyGrid-ItemLaunchedEffect同上同 LazyGrid但每个条目额外带一个模拟异步任务的LaunchedEffectLazyGrid-SmoothScroll同上同 LazyGrid但改用平滑滚动而非跳转LazyGrid-SmoothScroll-ItemLaunchedEffect同上组合了平滑滚动与条目内LaunchedEffectVisualEffectsvisualeffects/HappyNY.kt复杂动画与视觉特效雪花、星星、火箭粒子LazyListcomplexlazylist/components/MainUI.kt复杂LazyColumn下拉刷新、加载更多、持续滚动MultipleComponentsmultipleComponents/MultipleComponents.kt综合 UI布局、动画、样式化文本等大量组件同屏展示MultipleComponents-NoVectorGraphics同上同 MultipleComponents但跳过矢量图形渲染的 ComposableTextLayouttextlayout/TextLayout.kt连续滚动包含大量重排版条目的列测试文本布局与渲染性能CanvasDrawingcanvasdrawing/CanvasDrawing.kt滚动包含海量图形形状的条目测试 Canvas 绘制性能HeavyShaderheavyshader/HeavyShader.kt滚动包含复杂 GPU 着色器的条目测试 GPU 着色器性能源码级实现细节LazyGrid 系列LazyGrid.kt固定 4 列GridCells.Fixed(4)预生成 12000 个条目。跳转模式下每帧以 50 为步长执行state.scrollToItem(curItem)在列表头尾之间往返平滑滚动模式下改为每帧state.scrollBy(55f)或 -55f 反向。ItemLaunchedEffect变体在每个条目内启动一个LaunchedEffect其协程体执行suspendCoroutine { }挂起后永不恢复用于模拟条目作用域中存在长驻异步任务时的开销。VisualEffectsHappyNY.kt场景包含 80 片雪花snowCount、60 颗星星starCount与 30 个火箭粒子rocketPartsCount。雪花带有重力、正弦摆动与旋转相位星星为带旋转的十字形火箭采用两级爆炸模型——主火箭减速后分裂为 7 枚子火箭每枚再爆裂为 30 个带拖尾渐隐的粒子整体以withFrameNanos驱动逐帧状态更新。TextLayoutTextLayout.kt共 2000 个条目每个条目内嵌套 12 行 × 10 列的网格每个单元格均含小字号Text6.sp配合每帧scrollBy(67f)的持续滚动形成高密度的文本测量、排版与重绘压力。CanvasDrawingCanvasDrawing.kt1200 个条目每个条目 300.dp 高的 Canvas 内绘制 200 条渐变路径含quadraticBezierTo贝塞尔曲线、70 条摆动线条与 70 个脉动圆全部由无限动画驱动重点考验 Canvas 图元与渐变渲染吞吐。HeavyShaderHeavyShader.kt800 个条目每个 Canvas 内叠加 60 层径向渐变矩形layers 60逐层使用Screen、Overlay、Multiply三种BlendMode轮换混合另附 60 个BlendMode.Plus的光晕圆对 GPU 像素填充率与混合单元构成重度负载。LazyListMainUI.kt复刻真实社交信息流场景基于SwipeRefreshLayout实现下拉刷新delay(2000)模拟网络请求后重建数据与上滑加载更多同时内部以scrollBy(20f)保持持续滚动覆盖了含嵌套滚动手势的复杂懒加载列表性能。MultipleComponentsMultipleComponents.kt几乎集齐 Material 组件全家桶——TopAppBar、ExtendedFloatingActionButton、BottomAppBar、Switch、Checkbox、Slider、DropdownMenu、TextField、CircularProgressIndicator以及富文本buildAnnotatedString 内联Placeholder、BrushTextGradient/BrushTextImage渐变文本、10 万条目的右侧LazyColumn等。MultipleComponents-NoVectorGraphics变体通过isVectorGraphicsSupported false跳过Image与Icon等矢量资源绘制用于分离矢量渲染在总开销中的占比。结果输出与格式基准测试结果支持三种输出通道可自由组合JSONsaveStatsToJSONtrue结构化数据供脚本归档与版本对比使用归档路径为benchmarks/build/benchmarks/archive/${platform}/${version}_run${runIndex}CSVsaveStatsToCSVtrue表格化数据便于在电子表格工具中做进一步分析文本报告iOS 平台经.main.kts脚本运行时输出到benchmarks/build/benchmarks/text-reports/经.sh脚本运行时输出到benchmarks_result/。版本管理与场景实现适配从 settings.gradle.kts 的源码可以看出该基准测试项目对 Compose Multiplatform 版本变化做了精细的适配设计版本解析项目内置 Semver 解析器支持major.minor.patch[-preRelease][buildMetadata]格式并允许通过 Gradle 属性compose.version覆盖gradle/libs.versions.toml中声明的版本场景实现分代按 Compose Multiplatform 内部场景 API 的演进设置了两个分界点barriercompose-scene-impl-1基线版本使用ComposeScene.render(canvas, nanoTime)旧 APIcompose-scene-impl-2从 1.12.0-alpha02dev4213 起开始改用FrameRecomposer.performFrame()ComposeScene.measureAndLayout()ComposeScene.draw(canvas)拆分 APIcompose-scene-impl-3从 1.12.10-alpha01dev4534 起开始额外要求运行期调用registerSkikoComposeImplementation()注册 Skiko 图形与文本实现自包含复制每个实现模块都是前一个模块的完整自包含副本刻意保留重复代码以确保适配新 API 时绝不破坏旧版本仍能构建。这一机制保证了用旧版本跑基准与用新版本跑基准都能正确编译并链接到与之匹配的场景实现是version参数与compare_benchmarks/find_degradation脚本能够跨版本对比的前提。快速上手建议首次体验直接运行./gradlew :benchmarks:run使用默认的SIMPLEVSYNC_EMULATION模式快速验证桌面端渲染性能探索基准集先执行./gradlew :benchmarks:run -PrunArgumentslistBenchmarkstrue查看全部可用基准测试针对性测量使用benchmarksLazyGrid modesREAL frameCount200组合参数聚焦单个场景REAL 模式需在带真实显示器的设备上运行跨版本对比需要评估升级影响时用./compare_benchmarks.main.kts v1旧版本 v2新版本 platformmacos一键对比定位回退发现劣化后准备按从旧到新排序的版本清单文件用./find_degradation.main.kts benchmarks名称 versions版本文件二分定位引入回退的版本CI 集成无头环境建议使用VSYNC_EMULATION模式并配合saveStatsToJSONtrue将 JSON 结果归档到统一目录做持续回归监测。在阅读源码时建议以 benchmarks/src/commonMain/kotlin/benchmarks 下的各基准测试实现为入口结合 run_benchmarks.main.kts 了解脚本编排逻辑再对照 settings.gradle.kts 理解版本适配机制即可完整掌握这套跨平台性能基准体系的运行原理与扩展方式。【免费下载链接】compose-multiplatformCompose Multiplatform, a modern UI framework for Kotlin that makes building performant and beautiful user interfaces easy and enjoyable.项目地址: https://gitcode.com/GitHub_Trending/co/compose-multiplatform创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考