性能

性能特性

启动性能

JadeView 采用了轻量级架构设计,从项目启动到窗口显示的完整流程仅需 16 毫秒。这个数字是在易语言环境中测试得出的,

以下完整流程:

  1. 项目启动
  2. JadeView 初始化
  3. 创建 WebView 窗口
  4. 窗口成功显示

完整启动流程时间:300毫秒

以下完整流程:

  1. 项目启动
  2. JadeView 初始化
  3. 创建 WebView 窗口
  4. 窗口成功显示
  5. 加载 HTML 内容

与其他框架对比

以下启动流程皆不计算加载 HTML 内容时间:

框架完整启动流程时间启动流程架构优势
JadeView16毫秒项目启动 → 初始化 → 创建窗口 → 显示窗口Rust + wry极快启动,高性能,内存安全,线程安全,快速构建
Electron 231400毫秒项目启动 → 加载Chromium → 加载Node.js → 初始化 → 创建窗口 → 显示窗口Chromium + Node.js完整生态,跨平台
NW.js 0.70850毫秒项目启动 → 加载Chromium → 初始化 → 创建窗口 → 显示窗口Chromium + Node.js直接加载渲染进程,开发简单
CEF/CefSharp数百毫秒项目启动 → 加载Chromium → 初始化 → 创建窗口 → 显示窗口Chromium高性能,广泛应用

性能优势原因

  1. 轻量级架构:JadeView 基于 Rust 和 wry 库,不包含完整的 Node.js 运行时
  2. 按需加载:仅加载必要的组件,避免了不必要的资源消耗
  3. 高效的初始化流程:异步初始化设计,避免了阻塞主线程
  4. 优化的窗口创建:使用原生窗口系统,减少了中间层开销

内存安全

JadeView 基于 Rust 开发,继承了 Rust 的内存安全特性:

  1. 所有权模型:Rust 的所有权系统确保了内存安全,避免了内存泄漏和野指针
  2. 安全的字符串转换:使用 CStr::from_ptrCString::new 方法进行字符串转换
  3. 自动内存释放:所有分配的内存都会在适当的时候自动释放
  4. 无直接 malloc/free 调用:API 内部不直接使用 mallocfree,减少了内存泄漏风险
  5. 严格的生命周期控制:回调函数执行时,对象的生命周期被严格控制

线程安全

JadeView 的所有 API 函数都是线程安全的:

  1. 互斥锁保护:所有全局状态访问都通过互斥锁保护
  2. 无共享可变状态:设计上避免了共享可变状态
  3. 线程安全的回调机制:回调函数的执行环境是线程安全的
  4. 安全的资源访问:资源访问都经过严格的线程安全检查

异步架构

JadeView 采用了异步设计架构:

  1. 异步初始化:初始化过程是非阻塞的,允许应用在初始化期间进行其他操作
  2. 异步窗口创建create_webview_window 函数会立即返回窗口 ID,但窗口实际创建是在事件循环线程中异步完成的
  3. 事件驱动设计:通过事件回调机制处理各种窗口事件和 IPC 消息
  4. 高效的事件循环:基于 Rust 的高效事件循环实现

IPC 通信性能

JadeView 2.4 在 Windows 上重新设计了 send_ipc_message 的大消息传输路径:小于 1 MiB 的消息优先使用 WebView2 PostWebMessageAsString,大于或等于 1 MiB 的消息优先使用 SharedBuffer;WebView2 不支持 SharedBuffer 时仍可回退到 bulk_ref 分片拉取。前端继续通过 jade.on 接收消息,业务接口不变。

Python 压力测试说明

前端只显示已收到的数据包数量,并通过 jade.on('perfTick', handler) 接收消息。每个回调都会验证 payload:

  • 类型必须为字符串;
  • 长度必须严格等于 1,048,576 字节;
  • 只有完整数据到达前端后才计入接收数量。

因此 2.3.2 的 bulk_ref 必须完成分片拉取和重组后才算收到,2.4 的 SharedBuffer 也必须完成前端读取和 UTF-8 解码后才算收到。测试统计的不是宿主“已提交”数量或引用数量。

测试环境与参数

项目配置
操作系统Windows 11 专业工作站版,Build 26200
CPUIntel Core i5-14600KF,14 核 20 线程
内存31.84 GiB
WebView2 Runtime148.0.3967.96
Python3.11
资源采样psutil 7.2.2,统计 Python 宿主及 WebView2 子进程
单包大小1 MiB,即 1,048,576 字节
发送线程8 个 Python 线程
每轮包数20,000 包,即 19.53125 GiB
最大在途128 包,避免无约束队列一次堆积约 20 GiB 并导致系统 OOM
预热每轮正式测试前发送 256 包
正式轮次每版本 3 轮,交错执行

每个版本正式传输 58.59375 GiB,两版本合计传输 117.1875 GiB。下表使用三轮中位数。

2.4 与 2.3.2 实测对比

指标2.3.22.4.02.4 变化
前端完整接收吞吐315.305 包/s1255.185 包/s领先 298.086%
前端数据吞吐0.307915 GiB/s1.225767 GiB/s领先 298.086%
端到端耗时63.430612 s15.934096 s减少 74.879%
Python 宿主发送耗时63.162501 s15.881942 s减少 74.855%
前端排空耗时0.268111 s0.130052 s减少 51.493%
Python ctypes 调用 P501.365400 ms1.201400 ms减少 12.011%
Python ctypes 调用 P951.737005 ms1.652305 ms减少 4.876%
Python ctypes 调用 P992.495606 ms1.922835 ms减少 22.951%
进程树平均 CPU463.960%371.130%减少 20.008%
私有内存峰值1220.32 MiB269.23 MiB减少 77.938%
句柄峰值34173317减少 2.927%

按前端完整接收吞吐计算,JadeView 2.4 约为 2.3.2 的 3.981 倍

CPU 百分比为 Python 宿主和 WebView2 子进程的合计值,100% 约等于占用一个逻辑处理器。

稳定性与数据完整性

检查项2.3.22.4.0
正式运行完成3/33/3
Python 宿主发送60,00060,000
前端完整接收60,00060,000
包长/类型错误00
丢包数00
丢包率0%0%
send_ipc_message 返回失败00
Python/FFI 异常00
超时00
崩溃00
JadeView 日志 ERROR/WARN0/00/0

内存统计口径

2.4 的进程树 RSS 会高于 2.3.2,因为同一 SharedBuffer 页面可能同时映射到 Python 宿主和 WebView2 进程。把各进程 RSS 相加会重复统计共享页,不能直接解释为 2.4 独占了更多内存。

更适合比较实际独占提交压力的是私有内存峰值:2.4 的中位数从 1220.32 MiB 降至 269.23 MiB,减少 77.938%

结果适用范围

  • 结果针对 send_ipc_message 从宿主向前端发送 1 MiB UTF-8 大消息的场景。
  • Python ctypes 调用延迟包含 Python 线程调度和 FFI 开销,不等同于纯 C/Rust 微基准。
  • 实际性能会随 CPU、内存、WebView2 Runtime、消息大小、前端处理逻辑和最大在途数量变化。
  • 小消息、jade.invoke 请求响应、Linux WebKitGTK 以及没有背压的突发发送需要分别测试,不能直接套用本结果。

应用场景

2.4 的 SharedBuffer 路径适合以下宿主到前端的大消息场景:

  • 模型上下文、批量状态和大段文本同步
  • 实时监控或高频数据推送
  • 批量数据处理结果传输
  • 需要控制私有内存峰值的多窗口应用

接口定义、线程与返回值约定见 IPC 通信 API

jade.invoke 小请求/大响应性能

这一测试模拟更接近实际应用的请求-响应流程:前端只发送一个很小的通知字符串,Rust 主进程收到请求后返回大数据,前端等待 Promise 完成并验证完整结果。

Rust 测试程序说明

每次请求的完整链路为:

  1. 前端调用 jade.invoke('benchLarge', 'notify')
  2. 上行 payload 是 6 字节字符串 notify,表示一次通知。
  3. JadeView 调用 Rust register_ipc_handler 回调。
  4. Rust 通过 jade_text_create 返回由 ASCII x 组成的 1 MiB 字符串。
  5. JadeView 将结果包装为 invoke-async-response
  6. 2.3.2 使用 bulk_ref 分片拉取和重组;2.4 使用 WebView2 SharedBuffer。
  7. 前端 Promise 返回后,验证结果类型和长度;只有严格等于 1,048,576 字节才计为成功。

响应耗时定义

本测试的响应耗时由前端使用 performance.now() 记录:

JavaScript
const started = performance.now();
const result = await jade.invoke('benchLarge', 'notify');
const responseMs = performance.now() - started;

计时从前端发起 jade.invoke 开始,到 Promise 得到完整 1 MiB 返回值结束,包含:

  • 前端请求编码和自定义协议调用;
  • JadeView 请求解析与线程调度;
  • Rust 回调执行、1 MiB 结果分配和复制;
  • JadeView JSON 包装;
  • bulk_ref 或 SharedBuffer 回送;
  • 前端读取、解码、Promise 匹配和完整长度校验。

因此这里的 P50/P95/P99 是应用可感知的完整响应时间,不是单独某个 C API 的函数调用耗时。

测试参数

项目配置
Rust1.96.0,release 优化构建
请求方式jade.invoke('benchLarge', 'notify')
上行请求6 字节字符串 notify
下行响应1 MiB 字符串,即 1,048,576 字节
前端并发8 个并发 Promise;每个完成后再发下一个
每轮请求20,000 次,即返回 19.53125 GiB
预热每轮正式测试前 256 次
正式轮次每版本 3 轮,交错执行
资源采样Rust 内置 Windows 进程树采样,间隔 100 ms
测试环境与上一节 Python 推送测试相同

每个版本正式返回 58.59375 GiB,两版本合计返回 117.1875 GiB。以下数据使用三轮中位数。

Rust 请求-响应实测结果

指标2.3.22.4.02.4 变化
前端完整响应吞吐167.406 次/s731.237 次/s领先 336.805%
前端有效数据吞吐0.163483 GiB/s0.714099 GiB/s领先 336.803%
完成 20,000 次耗时119.4697 s27.3509 s减少 77.106%
响应平均耗时47.773130 ms10.934035 ms减少 77.113%
响应 P5047.600 ms10.400 ms减少 78.151%
响应 P9557.700 ms16.400 ms减少 71.577%
响应 P9961.900 ms21.100 ms减少 65.913%
响应最大值77.600 ms51.300 ms减少 33.892%
进程树平均 CPU370.770%526.470%增加 41.994%
完成固定任务的 CPU 核心秒444.688144.154减少 67.583%
RSS 峰值644.85 MiB811.13 MiB增加 25.786%
私有内存峰值456.45 MiB523.51 MiB增加 14.692%
句柄峰值35483102减少 12.570%

按前端完整响应吞吐计算,2.4 在这一 Rust 请求-大响应场景中约为 2.3.2 的 4.368 倍

CPU 与内存解释

2.4 的瞬时平均 CPU 更高,是因为它在相同时间内完成了约 4.37 倍的请求。对固定的 20,000 次任务计算 CPU 使用时间后:

  • 2.3.2 中位数为 444.688 CPU 核心秒;
  • 2.4 中位数为 144.154 CPU 核心秒;
  • 2.4 完成相同任务的总 CPU 工作量减少 67.583%。

本次 jade.invoke 测试中,2.4 的 RSS 和私有内存峰值高于 2.3.2。该链路同时存在 Rust jade_text_create 分配、JadeView 字符串复制、JSON 包装和 SharedBuffer 映射,不能沿用上一节 Python 单向推送测试的“私有内存下降”结论。

这也说明不同 IPC 使用方式必须分别测试:单向推送与请求-大响应的分配生命周期和并发模型不同。

稳定性与完整性

检查项2.3.22.4.0
正式运行完成3/33/3
Rust 回调请求数60,00060,000
前端完整响应数60,00060,000
notify 请求00
响应类型/长度错误00
jade.invoke 异常00
丢失响应00
丢失率0%0%
Rust/FFI 异常00
崩溃00
正常退出3/33/3
Windows Application Error/WER00

与 Python 单向推送测试的区别

  • Python 测试:宿主主动调用 send_ipc_message,前端被动接收;允许最多 128 个在途包。
  • Rust 测试:前端主动 jade.invoke,Rust 回调返回大数据;固定 8 个并发请求,每个 Promise 完成后再发送下一个。
  • Rust 测试额外包含上行请求、回调分配、JSON 结果包装和 Promise 请求 ID 匹配。

两组结果用于回答不同问题,绝对吞吐数字不能直接横向比较。两组测试都表明 2.4 的 SharedBuffer 大消息路径相对 2.3.2 的 bulk_ref 有显著性能优势。

设计理念

简洁易用

JadeView 的 API 设计注重简洁易用:

  1. 直观的函数命名:函数名称清晰反映其功能
  2. 合理的参数设计:参数数量和类型设计合理,易于理解和使用
  3. 完整的文档:提供详细的 API 文档和使用示例
  4. 良好的错误处理:提供清晰的错误信息和错误处理机制

跨平台兼容

JadeView 目前支持 Windows 与 Linux 平台(暂不支持 macOS),其设计也充分考虑了跨平台兼容性:

  1. 抽象的窗口接口:设计了抽象的窗口接口,便于添加其他平台支持
  2. 标准化的 API:API 设计遵循跨平台标准
  3. 模块化设计:核心功能与平台特定代码分离

安全优先

安全是 JadeView 设计的核心原则:

  1. Rust 语言安全特性:利用 Rust 的类型系统和所有权模型确保安全
  2. 严格的输入验证:所有 API 输入都经过严格验证
  3. 安全的 IPC 机制:IPC 通信经过安全设计,避免了安全漏洞
  4. 最小权限原则:遵循最小权限原则,减少潜在的安全风险

技术栈

JadeView 采用了现代化的技术栈:

  • Rust:核心开发语言,提供内存安全和高性能
  • wry:WebView 库,JadeView 基于 WebView2 (Windows) 与 WebKitGTK (Linux);目前不支持 macOS
  • tao:窗口管理库,提供跨平台窗口管理功能与事件循环
  • serde:序列化/反序列化库,用于数据传输
  • crossbeam-channel:线程间消息通道;JadeView 不依赖 tokio,异步基于 tao 事件循环 + crossbeam-channel 实现

架构设计

JadeView 采用了分层架构设计:

  1. 核心层:包含内存管理、事件循环和基础功能
  2. API 层:提供 C 语言兼容的 API 接口
  3. SDK 层:为不同语言(如易语言)提供 SDK 封装
  4. 应用层:用户应用程序

这种分层设计使得 JadeView 具有良好的扩展性和可维护性,便于添加新的平台支持和功能。

未来发展

通过持续的优化和改进,JadeView 将继续保持高性能、高安全性和易用性的特点,为开发者提供更好的 WebView 窗口库解决方案。