基于 BrowserStack 的多设备 TensorFlow.js 推理性能基准测试工具实战指南

发布时间:2026/9/20 21:22:07
基于 BrowserStack 的多设备 TensorFlow.js 推理性能基准测试工具实战指南 基于 BrowserStack 的多设备 TensorFlow.js 推理性能基准测试工具实战指南【免费下载链接】tfjsA WebGL accelerated JavaScript library for training and deploying ML models.项目地址: https://gitcode.com/gh_mirrors/tf/tfjs本指南以 browserstack-benchmark 工具文档 为核心骨架结合 e2e/benchmarks/browserstack-benchmark 目录下的真实源码app.js、benchmark_models.js、karma.conf.js、preconfigured_browser.json 等进行深度展开帮助你完整掌握如何在数十台真实远程设备上横向评测 TFJS 模型的推理耗时与内存峰值如何用预配置文件批量跑基准以及如何用 12 个命令行参数控制整个基准流程。工具是什么一次跑遍几十台真机的 TFJS 性能评测在浏览器端部署 TensorFlow.js 模型时开发者最关心的问题往往是这个模型在不同操作系统、不同浏览器、不同档次的手机上推理到底有多快、吃多少内存单机自测只能回答我这台机器上跑得怎样无法回答用户的 iPhone 13、Pixel 6、三星 S22 上跑得怎样。browserstack-benchmark正是 TFJS 官方仓库tfjs/e2e/benchmarks/目录提供的多设备基准测试工具。它借助BrowserStack Automate云真机服务在一批远程浏览器/真机上统一执行模型推理基准收集推理时间与内存占用两类指标。使用该工具你可以基于OS、OS 版本、浏览器、浏览器版本、设备型号五个字段挑选一批目标设备桌面浏览器 iOS/Android 真机选择推理后端WASM / WebGL / CPU设置模型推理轮数numRuns选择要基准的模型官方内置模型、远程 URL 自定义模型或任意代码片段 codeSnippet。需要提醒的是使用该工具前你必须注册 BrowserStack 的 Automate 付费/试用服务并准备好账号的用户名与 Access Key工具本身无法脱离 BrowserStack 云设备运行除非只用local模式跑本机 Chrome。工具的三段式架构Karma 测试运行器 Node 服务端 Web 页面从仓库源码看工具由三个部分协同工作见 About this tool 章节Karma 测试运行器benchmark_models.js 把所有基准逻辑封装成一个 Jasmine specdescribe(BrowserStack benchmark)由 Karma 在目标浏览器中执行browser_list.json 罗列了官方支持的 BrowserStack 设备组合清单。Node 服务端app.js 负责拉起 Karma 测试运行器并通过 socket.io 把基准结果回传网页。Web 页面index.html index.js 提供可视化操作界面与结果展示。关键调用链在源码中清晰可见app.js的runServer()用 Node 原生http模块起静态文件服务默认端口 8001可通过环境变量PORT覆盖并挂载 socket.io浏览器连接后服务端立即下发availableBrowsers即browser_list.json内容随后监听前端发来的run事件触发benchmark()。benchmark()调用setupBenchmarkEnv()生成两份供 Karma 读取的临时配置./browsers.jsontabId → 浏览器配置映射与./benchmark_parameters.json模型、backend、numRuns 等基准参数。这里有一个值得注意的实现细节当目标 OS 是ios或android时源码会自动追加real_mobile true即移动端一律使用真机而非模拟器。对每个浏览器实例runBrowserStackBenchmark()实际执行yarn test --browserstack --browserstabId必要时追加--localBuild/--npmVersion然后在 Karma 的 stdout 中用正则解析tfjs_benchmark.../tfjs_benchmark或tfjs_error.../tfjs_error标记得到结构化结果或错误信息这两个标记由 benchmark_models.js 在 Jasmine spec 内console.log输出。Karma 端如何装配依赖karma.conf.js 揭示了三种依赖加载模式由 CLI 参数切换默认走CDNhttps://unpkg.com/tensorflow/packagelatest/...指定--npmVersion时改为https://unpkg.com/tensorflow/packageversion/...指定--localBuild时从../../../dist/bin/加载本地构建产物tf-core.js、tf-backend-cpu.js、tf-backend-webgl.js、tf-layers.js、tf-converter.js、tf-backend-wasm.js、tf-automl.js等 7 个文件按需选取。同时 Karma 通过karma-browserstack-launcher建立本地隧道hostname: bs-local.com随机tunnelIdentifier并把./browsers.json的内容直接注入customLaunchers。benchmark_models.js在 Jasmine 的beforeAll中通过fetch(./base/benchmark_parameters.json)拉取基准参数并执行tf.setBackend(targetBackend)完成后端切换。环境准备与快速上手第一步导出 BrowserStack 凭据app.js的checkBrowserStackAccount()会在启动时强校验两个环境变量缺失会直接抛错并提示导出命令export BROWSERSTACK_USERNAMEYOUR_USERNAME export BROWSERSTACK_ACCESS_KEYYOUR_ACCESS_KEY第二步下载依赖并启动git clone https://github.com/tensorflow/tfjs.git cd tfjs/e2e/benchmarks/browserstack-benchmark yarn install node app.js启动成功后终端会输出 Running socket on: 127.0.0.1:8001注意源码日志写的是127.0.0.1:${port}README 中描述为Running socket on port: 8001实际端口由环境变量PORT决定默认 8001。第三步打开网页开始基准浏览器访问http://localhost:8001/。页面由 index.js 驱动提供以下交互能力从服务端下发的设备清单中选择浏览器/设备通过Add browser加入待测列表默认状态为 OS X Monterey Chrome 103.0选择模型model、推理轮数numRuns默认 10、后端backend默认 webgl点击Run benchmark后服务端为每个 tabId 创建独立 Karma 实例并行开跑结果通过 socket.io分批回传谁先跑完谁先展示并在页面表格中实时标记状态等待灰#AAAAAA、完成蓝#357edd、出错红#e8564b。基准一个自定义代码片段codeSnippet页面内置的代码片段基准功能默认值在 index.js 中可以看到例如一个随机输入上的tf.conv2d卷积setupCodeSnippetEnv: const img tf.randomUniform([1, 240, 240, 3], 0, 1000); const filter tf.randomUniform([3, 3, 3, 3], 0, 1000);, codeSnippet: predict () { return tf.conv2d(img, filter, 2, \same\);};注意通过网页基准 codeSnippet 时需要在运行node app.js之前更新 index.js 中state.benchmark的codeSnippet/setupCodeSnippetEnv字段然后在页面的模型下拉框中选择codeSnippet。benchmark_models.js 中的benchmarkCodeSnippet()会eval拼接后的代码要求其中必须定义名为predict的函数随后先做 1 次预热再正式计时numRuns轮并做内存 profile。预配置文件一条命令批量跑完模型 × 后端 × 设备矩阵对于 CI 或周期化回归官方推荐使用--benchmarks参数从预配置 JSON 文件驱动node app.js --benchmarksrelative_file_path.json仓库自带的 preconfigured_browser.json 就是一份可直接参考的完整示例。配置文件的格式如下{ benchmark: { model: [model_name], numRuns: positive_integer, backend: [backend_name] }, browsers: { local: {}, unique_identifier_laptop_or_desktop: { base: BrowserStack, browser: browser_name, browser_version: browser_version, os: os_name, os_version: os_version, device: null }, unique_identifier_mobile_device: { base: BrowserStack, browser: iphone_or_android, browser_version: null, os: os_name, os_version: os_version, device: device_name } } }字段说明benchmark.model一个或多个要基准的模型名官方内置模型名或custom见下文Custom modelbenchmark.numRuns每个模型的推理轮数必须为正整数benchmark.backend一个或多个后端名如[webgl]、[wasm, cpu]browsers以唯一标识符为键的浏览器配置映射local键代表本机执行无 BrowserStack 依赖其余每个键代表一台远程设备。桌面设备用browserbrowser_versionosos_versiondevice: null描述移动设备用browser: iphone|androiddevice描述真实机型browser_version: null。配置文件中的base: BrowserStack会在运行时被 app.js 的 setupBenchmarkEnv() 再次补全并自动为 iOS/Android 设备加上real_mobile: true。执行语义见 benchmarkAll() 的嵌套循环模型列表中的每个模型 × 后端列表中的每个后端组合成一组基准每组基准会在每一个浏览器配置上执行。也就是说最终的基准次数 模型数 × 后端数 × 浏览器数。如果你想针对特定模型 × 特定后端做组合README 明确建议拆分成多个配置文件分别执行。仓库内相关文件官方支持的 BrowserStack 设备/浏览器组合清单browser_list.json涵盖 Windows/OS X 桌面端 Chrome/Edge/Firefox/Safari/IE以及 iOSiPhone/iPad与 Android 真机如 iPhone 13 Pro Max、Google Pixel 6 Pro、Samsung Galaxy S22 Ultra、Xiaomi Redmi Note 8 等官方示例预配置preconfigured_browser.json内置 24 个模型的基准列表 17 台真机配置numRuns: 10backend: [webgl]。命令行参数全解12 个选项工具使用argparse解析参数定义见 setupHelpMessage()在仓库目录下运行node app.js --h或--help可在终端查看完整帮助菜单。全部参数如下参数作用示例--benchmarks从用户指定的预配置 JSON 文件运行基准文件路径需相对仓库目录node app.js --benchmarksrelative_file_path.json--cloud以 GCP 兼容模式运行不启动本地服务器不监听页面、不回传 socket适合云上 CInode app.js --cloud--firestore把成功的基准结果推送到 Firestore 数据库node app.js --firestore--h/--help在终端显示帮助菜单与全部可选参数node app.js --h--period将--benchmarks文件中的模型列表按每月日期循环切分为若干桶只跑其中一桶取值 1~31。仅在设置了--benchmarks时生效node app.js --period15--date手动指定用于选择模型的日期1~31仅在设置了--period时生效未声明则使用运行当天日期node app.js --period15 --date1--maxBenchmarks并行执行的基准数量上限正整数默认 5node app.js --maxBenchmarkspositive_integer--maxTries单个基准失败后的最大重试次数正整数默认 3node app.js --maxTriespositive_integer--outfile把结果写入外部文件期望值为html或json。设为html生成benchmark_results.js可打开benchmark_result.html离线查看node app.js --outfilejs--v/--version显示当前使用的 node 版本node app.js --v--localBuild使用本地构建产物替代公共 CDN。使用前务必先构建对应目标例如yarn build-individual-link-package tfjs-backend-webglnode app.js --localBuildcore,webgl,wasm,cpu,layers,converter,automl--npmVersion指定要基准的 TFJS npm 版本默认基准最新版node app.js --npmVersion4.4.0关键参数的源码级解读--maxBenchmarks默认 5与--maxTries默认 3benchmark()内部使用仓库自实现的 promise_queue.js 控制并发每个 tabId 的基准都会进入队列最多maxBenchmarks个同时运行。重试逻辑在 getOneBenchmarkResult()失败后递归重试直到maxTries用完。源码还处理了一个工程细节——多个 Karma 进程同时拉起会触发spawn ETXTBSY竞争错误因此每次启动基准前会按tabIndex * (3 ** numFailed) * 1000毫秒指数退避地错峰启动 runner。--period/--date的调度算法见 scheduleModels()。模型列表被均匀切成period个桶bucketSize Math.ceil(models.length / period)按(date - 1) % period选中其中一个桶。参数越界period或date不在 1~31会直接抛出异常。这非常适合每天只跑 1/15 的模型半月轮转一遍的持续回归场景——仓库 package.json 中的run-cloud-benchmarks-half-month-cycle脚本正是这么用的。--outfile启动时若指定html会先写const benchmarkResults 前缀到benchmark_results.js再通过JSONStream把每个基准结果流式追加指定json则写入benchmark_results.json。结果可通过 benchmark_results.html 离线渲染成表格按Model/Code Snippetbackend分表展示OS(版本) 设备与目标名称等字段。--firestoreinitializeWriting()中通过 firestore.js 初始化 FirebasepushToFirestore()只把status fulfilled的结果写入数据库被拒绝的 Promise 只计数并打印见 app.js。--localBuild的命名规则源码注释明确参数值是包名的短形式——一般去掉tfjs-与backend-前缀例如webgl对应tfjs-backend-webglcore对应tfjs-core。仓库 package.json 提供了配套构建脚本yarn build-all-deps构建全部 link 包 tfjs 本体、yarn build-individual-link-package构建单个依赖。内置模型与自定义模型Custom modele2e/benchmarks目录下的 model_config.js 以benchmarks对象集中登记了所有官方内置模型。每个模型条目包含typeGraphModel/LayersModel、load()加载函数含默认输入分辨率与架构参数如 MobileNetV3 的small_075/small_100/large_075/large_100、predictFunc()返回带固定随机/零值输入的预测函数。从源码可见内置模型覆盖了图像分类MobileNetV3、MobileNetV2、姿态估计MoveNet-SinglePose、MoveNet-MultiPose、posenet、手势HandPoseDetector、HandPoseLandmark、检测Coco-SSD、BlazePose、分割DeepLabV3、BodyPix、SelfieSegmentation、文本Universal Sentence Encoder、TextToxicity、MobileBert、语音speech-commands以及 AutoML 系列等 20 余个模型。如果你想基准自定义模型需要满足以下约束必须提供模型的 URL 路径不支持本地文件系统模型。例如TF Hubhttps://tfhub.dev/google/tfjs-model/imagenet/resnet_v2_50/feature_vector/1/default/1对象存储https://storage.googleapis.com/tfjs-models/savedmodel/mobilenet_v2_1.0_224/model.json目前仅支持tf.GraphModel与tf.LayersModel两种模型类型。如果你的模型需要更复杂的输入预处理逻辑就需要把模型连同load与predictFunc两个方法注册进 e2e/benchmarks/model_config.js。加载与推断的接线逻辑在 benchmark_models.js 的 benchmarkModel()优先使用模型自带的predictFunc否则调用 benchmark_util.js 的 generateInput() 依据model.inputs的 shape/dtype 自动生成随机输入shape 中的-1/null会被替换为 1float32/int32 输入按 [0, 1000] 区间、近似正态分布生成并裁剪再走timeModelInference/profileModelInference。输入生成失败时所有已创建的 tensor 会被统一dispose()防止内存泄漏。指标口径工具到底在测什么结果由 benchmark_util.js 统一计算两条主线分别对应 README 强调的time时间与memory内存时间指标timeInference()timeInfotimes每一轮推理的耗时数组averageTime全部轮次平均耗时averageTimeExclFirst剔除第一轮后的平均耗时——第一轮通常包含 WebGL shader 编译等冷启动开销因此这个值更能反映稳态性能minTime/maxTime最慢/最快耗时。计时范围包含predict()与对结果张量调用data()/dataSync()的完整链路因此是端到端可用结果的耗时对 WebGL 后端使用同步dataSync()强制 GPU 计算完成。此外 timeFirstInference() 支持通过ENGINE_COMPILE_ONLY标志测量带并行编译的首轮推理耗时WebGL/WebGPU 后端。内存指标profileInference()基于tf.profilenewBytes新增分配的字节数newTensors新增创建的 tensor 数量peakBytes内存分配峰值kernels每个 kernel 的输入/输出 shape、字节数、耗时明细按耗时降序aggregatedKernels按 kernel 名称聚合后的耗时{name, timeMs}降序。环境信息benchmark_models.js的getEnvSummary()会附加后端版本信息——WebGL 后端带WEBGL_VERSIONWASM 后端标注是否启用 SIMD通过WASM_HAS_SIMD_SUPPORTWebGL 后端还会通过WEBGL_debug_renderer_info扩展抓取真实的 GPU 渲染器字符串见 getRendererInfo()。最终 getBenchmarkSummary() 汇总成1st inference time、Subsequent average inference timeN runs、Best inference time、Peak memory四段摘要这与 README 中benchmark the time and memory的目标一一对应。完整基准流程回放结合源码一次完整的 BrowserStack 多设备基准可以总结为以下链路node app.js [options]→checkBrowserStackAccount()校验凭据 → 按需初始化 Firestore/结果文件非--cloud模式下启动静态服务 socket.io端口 8001页面从服务端拿到browser_list.json设备清单用户在页面配置浏览器/模型/后端/轮数或通过--benchmarks加载预配置文件服务端为每台设备生成browsers.json与benchmark_parameters.json通过PromiseQueue控制并发为每个 tabId 依次/并行拉起yarn test --browserstack --browserstabIdKarmaKarma 在远端浏览器中由benchmark_models.js执行 Jasmine spectf.setBackend(后端)→ 加载模型/执行代码片段 →timeInferenceprofileInference→ 以tfjs_benchmark{JSON}/tfjs_benchmark输出服务端解析结果失败则按maxTries指数退避重试成功则通过 socket 回传页面实时展示并按需写入--outfile文件或推送 Firestore。这套链路使得多模型 × 多后端 × 多设备的矩阵基准可以全自动化运行——仓库 package.json 中现成的 CI 脚本即为最佳实践yarn run-cloud-benchmarks # node app.js --benchmark./preconfigured_browser.json --cloud --maxBenchmarks12 --firestore yarn run-cloud-benchmarks-half-month-cycle # 加上 --period15按日期轮转模型使用前提与注意事项必须拥有 BrowserStack Automate 账号并正确导出BROWSERSTACK_USERNAME/BROWSERSTACK_ACCESS_KEY否则node app.js启动即报错移动端设备为真机real_mobile: true会真实消耗 BrowserStack 额度注意--maxBenchmarks并发数与--period切分以控制成本依赖清单见 package.jsonkarma、karma-browserstack-launcher、karma-jasmine、socket.io、argparse、firebase-adminFirestore、JSONStream 等需使用 yarnengines.yarn 1.0.0使用--localBuild前必须先构建对应本地包否则会加载失败--period/--date依赖--benchmarks两者单独使用不生效--date依赖--period本工具针对 WebGL/WASM/CPU 三类传统浏览器后端设计benchmark_models.js通过tf.setBackend切换TFLite 等特殊后端仅通过特定模型配置与代码路径支持。现在你已经可以动手构建属于自己的多设备基准矩阵从browser_list.json挑设备、在preconfigured_browser.json里配模型与后端再把它接进--period的月度轮转让 TFJS 在真实终端上的性能表现持续处于你的监控之下。【免费下载链接】tfjsA WebGL accelerated JavaScript library for training and deploying ML models.项目地址: https://gitcode.com/gh_mirrors/tf/tfjs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考