性能
性能特性
启动性能
JadeView 采用了轻量级架构设计,从项目启动到窗口显示的完整流程仅需 16 毫秒。这个数字是在易语言环境中测试得出的,
以下完整流程:
- 项目启动
- JadeView 初始化
- 创建 WebView 窗口
- 窗口成功显示
完整启动流程时间:300毫秒
以下完整流程:
- 项目启动
- JadeView 初始化
- 创建 WebView 窗口
- 窗口成功显示
- 加载 HTML 内容
与其他框架对比
以下启动流程皆不计算
加载 HTML 内容时间:
框架 完整启动流程时间 启动流程 架构 优势 JadeView 16毫秒 项目启动 → 初始化 → 创建窗口 → 显示窗口 Rust + wry 极快启动,高性能,内存安全,线程安全,快速构建 Electron 23 1400毫秒 项目启动 → 加载Chromium → 加载Node.js → 初始化 → 创建窗口 → 显示窗口 Chromium + Node.js 完整生态,跨平台 NW.js 0.70 850毫秒 项目启动 → 加载Chromium → 初始化 → 创建窗口 → 显示窗口 Chromium + Node.js 直接加载渲染进程,开发简单 CEF/CefSharp 数百毫秒 项目启动 → 加载Chromium → 初始化 → 创建窗口 → 显示窗口 Chromium 高性能,广泛应用
性能优势原因
- 轻量级架构:JadeView 基于 Rust 和 wry 库,不包含完整的 Node.js 运行时
- 按需加载:仅加载必要的组件,避免了不必要的资源消耗
- 高效的初始化流程:异步初始化设计,避免了阻塞主线程
- 优化的窗口创建:使用原生窗口系统,减少了中间层开销
内存安全
JadeView 基于 Rust 开发,继承了 Rust 的内存安全特性:
- 所有权模型:Rust 的所有权系统确保了内存安全,避免了内存泄漏和野指针
- 安全的字符串转换:使用
CStr::from_ptr和CString::new方法进行字符串转换 - 自动内存释放:所有分配的内存都会在适当的时候自动释放
- 无直接 malloc/free 调用:API 内部不直接使用
malloc和free,减少了内存泄漏风险 - 严格的生命周期控制:回调函数执行时,对象的生命周期被严格控制
线程安全
JadeView 的所有 API 函数都是线程安全的:
- 互斥锁保护:所有全局状态访问都通过互斥锁保护
- 无共享可变状态:设计上避免了共享可变状态
- 线程安全的回调机制:回调函数的执行环境是线程安全的
- 安全的资源访问:资源访问都经过严格的线程安全检查
异步架构
JadeView 采用了异步设计架构:
- 异步初始化:初始化过程是非阻塞的,允许应用在初始化期间进行其他操作
- 异步窗口创建:
create_webview_window函数会立即返回窗口 ID,但窗口实际创建是在事件循环线程中异步完成的 - 事件驱动设计:通过事件回调机制处理各种窗口事件和 IPC 消息
- 高效的事件循环:基于 Rust 的高效事件循环实现
IPC 通信性能
JadeView 2.4 在 Windows 上重新设计了 send_ipc_message 的大消息传输路径:小于 1 MiB 的消息优先使用 WebView2 PostWebMessageAsString,大于或等于 1 MiB 的消息优先使用 SharedBuffer;WebView2 不支持 SharedBuffer 时仍可回退到 bulk_ref 分片拉取。前端继续通过 jade.on 接收消息,业务接口不变。
Python 压力测试说明
本节不是 Rust 内部微基准,也不是 C/C++ 示例程序测试。测试宿主使用 Python 3.11,通过 ctypes.WinDLL 加载 JadeView_x64.dll,由 ThreadPoolExecutor 创建 8 个 Python 发送线程并发调用 send_ipc_message。
ctypes 外部函数调用期间会释放 Python GIL,因此 8 个线程可以并发进入 DLL。结果包含 Python 调度、FFI 调用、JadeView 消息队列、WebView2 传输和前端完整接收的综合开销。
前端只显示已收到的数据包数量,并通过 jade.on('perfTick', handler) 接收消息。每个回调都会验证 payload:
- 类型必须为字符串;
- 长度必须严格等于 1,048,576 字节;
- 只有完整数据到达前端后才计入接收数量。
因此 2.3.2 的 bulk_ref 必须完成分片拉取和重组后才算收到,2.4 的 SharedBuffer 也必须完成前端读取和 UTF-8 解码后才算收到。测试统计的不是宿主“已提交”数量或引用数量。
测试环境与参数
| 项目 | 配置 |
|---|---|
| 操作系统 | Windows 11 专业工作站版,Build 26200 |
| CPU | Intel Core i5-14600KF,14 核 20 线程 |
| 内存 | 31.84 GiB |
| WebView2 Runtime | 148.0.3967.96 |
| Python | 3.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.2 | 2.4.0 | 2.4 变化 |
|---|---|---|---|
| 前端完整接收吞吐 | 315.305 包/s | 1255.185 包/s | 领先 298.086% |
| 前端数据吞吐 | 0.307915 GiB/s | 1.225767 GiB/s | 领先 298.086% |
| 端到端耗时 | 63.430612 s | 15.934096 s | 减少 74.879% |
| Python 宿主发送耗时 | 63.162501 s | 15.881942 s | 减少 74.855% |
| 前端排空耗时 | 0.268111 s | 0.130052 s | 减少 51.493% |
Python ctypes 调用 P50 | 1.365400 ms | 1.201400 ms | 减少 12.011% |
Python ctypes 调用 P95 | 1.737005 ms | 1.652305 ms | 减少 4.876% |
Python ctypes 调用 P99 | 2.495606 ms | 1.922835 ms | 减少 22.951% |
| 进程树平均 CPU | 463.960% | 371.130% | 减少 20.008% |
| 私有内存峰值 | 1220.32 MiB | 269.23 MiB | 减少 77.938% |
| 句柄峰值 | 3417 | 3317 | 减少 2.927% |
按前端完整接收吞吐计算,JadeView 2.4 约为 2.3.2 的 3.981 倍。
CPU 百分比为 Python 宿主和 WebView2 子进程的合计值,100% 约等于占用一个逻辑处理器。
稳定性与数据完整性
| 检查项 | 2.3.2 | 2.4.0 |
|---|---|---|
| 正式运行完成 | 3/3 | 3/3 |
| Python 宿主发送 | 60,000 | 60,000 |
| 前端完整接收 | 60,000 | 60,000 |
| 包长/类型错误 | 0 | 0 |
| 丢包数 | 0 | 0 |
| 丢包率 | 0% | 0% |
send_ipc_message 返回失败 | 0 | 0 |
| Python/FFI 异常 | 0 | 0 |
| 超时 | 0 | 0 |
| 崩溃 | 0 | 0 |
| JadeView 日志 ERROR/WARN | 0/0 | 0/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 测试程序说明
测试宿主使用 Rust 1.96.0 编写,通过 libloading 动态加载 JadeView_x64.dll,使用 register_ipc_handler 注册 benchLarge 处理器,并通过 jade_text_create 返回 1 MiB 字符串。
资源采样同样在 Rust 测试进程内完成,通过 Windows 进程 API 统计 Rust 宿主及 WebView2 子进程;PowerShell 只负责隔离启动各轮进程和汇总 JSON,不参与被测进程,也不计入 CPU 或内存数据。
每次请求的完整链路为:
- 前端调用
jade.invoke('benchLarge', 'notify')。 - 上行 payload 是 6 字节字符串
notify,表示一次通知。 - JadeView 调用 Rust
register_ipc_handler回调。 - Rust 通过
jade_text_create返回由 ASCIIx组成的 1 MiB 字符串。 - JadeView 将结果包装为
invoke-async-response。 - 2.3.2 使用
bulk_ref分片拉取和重组;2.4 使用 WebView2 SharedBuffer。 - 前端 Promise 返回后,验证结果类型和长度;只有严格等于 1,048,576 字节才计为成功。
响应耗时定义
本测试的响应耗时由前端使用 performance.now() 记录:
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 的函数调用耗时。
测试参数
| 项目 | 配置 |
|---|---|
| Rust | 1.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.2 | 2.4.0 | 2.4 变化 |
|---|---|---|---|
| 前端完整响应吞吐 | 167.406 次/s | 731.237 次/s | 领先 336.805% |
| 前端有效数据吞吐 | 0.163483 GiB/s | 0.714099 GiB/s | 领先 336.803% |
| 完成 20,000 次耗时 | 119.4697 s | 27.3509 s | 减少 77.106% |
| 响应平均耗时 | 47.773130 ms | 10.934035 ms | 减少 77.113% |
| 响应 P50 | 47.600 ms | 10.400 ms | 减少 78.151% |
| 响应 P95 | 57.700 ms | 16.400 ms | 减少 71.577% |
| 响应 P99 | 61.900 ms | 21.100 ms | 减少 65.913% |
| 响应最大值 | 77.600 ms | 51.300 ms | 减少 33.892% |
| 进程树平均 CPU | 370.770% | 526.470% | 增加 41.994% |
| 完成固定任务的 CPU 核心秒 | 444.688 | 144.154 | 减少 67.583% |
| RSS 峰值 | 644.85 MiB | 811.13 MiB | 增加 25.786% |
| 私有内存峰值 | 456.45 MiB | 523.51 MiB | 增加 14.692% |
| 句柄峰值 | 3548 | 3102 | 减少 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.2 | 2.4.0 |
|---|---|---|
| 正式运行完成 | 3/3 | 3/3 |
| Rust 回调请求数 | 60,000 | 60,000 |
| 前端完整响应数 | 60,000 | 60,000 |
非 notify 请求 | 0 | 0 |
| 响应类型/长度错误 | 0 | 0 |
jade.invoke 异常 | 0 | 0 |
| 丢失响应 | 0 | 0 |
| 丢失率 | 0% | 0% |
| Rust/FFI 异常 | 0 | 0 |
| 崩溃 | 0 | 0 |
| 正常退出 | 3/3 | 3/3 |
| Windows Application Error/WER | 0 | 0 |
与 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 设计注重简洁易用:
- 直观的函数命名:函数名称清晰反映其功能
- 合理的参数设计:参数数量和类型设计合理,易于理解和使用
- 完整的文档:提供详细的 API 文档和使用示例
- 良好的错误处理:提供清晰的错误信息和错误处理机制
跨平台兼容
JadeView 目前支持 Windows 与 Linux 平台(暂不支持 macOS),其设计也充分考虑了跨平台兼容性:
- 抽象的窗口接口:设计了抽象的窗口接口,便于添加其他平台支持
- 标准化的 API:API 设计遵循跨平台标准
- 模块化设计:核心功能与平台特定代码分离
安全优先
安全是 JadeView 设计的核心原则:
- Rust 语言安全特性:利用 Rust 的类型系统和所有权模型确保安全
- 严格的输入验证:所有 API 输入都经过严格验证
- 安全的 IPC 机制:IPC 通信经过安全设计,避免了安全漏洞
- 最小权限原则:遵循最小权限原则,减少潜在的安全风险
技术栈
JadeView 采用了现代化的技术栈:
- Rust:核心开发语言,提供内存安全和高性能
- wry:WebView 库,JadeView 基于 WebView2 (Windows) 与 WebKitGTK (Linux);目前不支持 macOS
- tao:窗口管理库,提供跨平台窗口管理功能与事件循环
- serde:序列化/反序列化库,用于数据传输
- crossbeam-channel:线程间消息通道;JadeView 不依赖 tokio,异步基于 tao 事件循环 + crossbeam-channel 实现
架构设计
JadeView 采用了分层架构设计:
- 核心层:包含内存管理、事件循环和基础功能
- API 层:提供 C 语言兼容的 API 接口
- SDK 层:为不同语言(如易语言)提供 SDK 封装
- 应用层:用户应用程序
这种分层设计使得 JadeView 具有良好的扩展性和可维护性,便于添加新的平台支持和功能。
未来发展
通过持续的优化和改进,JadeView 将继续保持高性能、高安全性和易用性的特点,为开发者提供更好的 WebView 窗口库解决方案。