V8 JS AOT化的探索与实践

如果无法正常显示,请先停止浏览器的去广告插件。
分享至:
1. 第 十 六 届 D 2 前 端 技 术 论 坛 V8 JS AOT化的探索与实践 喻世江
2. 背 景 技术选型 目录 方案设计 优化效果 展 望
3. 背 景
4. 背 景 U4内核V8引擎 快 强 JavaScript ü Disk Code Cache ü UC LLVM Compiler 跨平台 ü JS 卡死检测 动态化 ü OOM 定位信息 ü JS API 扩展 性能 ü JSI 稳 Native ü 疑难崩溃攻克 Ø 运行时在线编译 Ø 打包时 PC 离线编译 ü 安全漏洞修复 Ø 每次重新编译 Ø 直接运行
5. 背 景 JS AOT AOT:Ahead of Time,提前编译。 目标 让 JavaScript 具备动态化特性的同时,运行性能也可能与 Native 对标,尤其是首次启动。
6. 技术选型
7. 技术选型 V8 运行 JavaScript 的流水线 JavaScript Source Code function test(o) { return 3 + o.x; } Parser Abstract Syntax Tree Ignition TurboFan Bytecode StackCheck LdaSmi [3] Star r0 LdaNamedProperty a0, [0], [1] Add r0, [0] Return Optimized Machine Code REX.W leaq rbx,[rip+0xfffffff9] REX.W cmpq rbx,rcx jz 0x1efffc744 <+0x24> REX.W movq rdx,0x3e00000 REX.W movq r10,0x7f2be00 call r10 int3l REX.W movq rbx,[rcx-0x20] testb [rbx+0xf],0x1 ...
8. 技术选型 本地代码 (Machine Code,汇编) 全字节码缓存 (Full Code Cache) 部分字节码缓存 (Code Cache)
9. 技术选型 调研一:使用本地代码(Machine Code,汇编) 2010 年 V8 : JavaScript Source Code Full-codegen Parser Abstract Syntax Tree ToString Unoptimized Machine Code 体积大 内存高 Crankshaft operator + 编译慢 性能差 Optimized Machine Code ToNumber CPU 架构不通用 ToPrimitive GetMethod GetV ToObject GetValue Call
10. 技术选型 调研二:缓存全部字节码(Full Code Cache) Ø JS 函数运行覆盖度低(43%) 350.0 运行函数个数 全字节码大小 JS源码大小 Ø 加载 & 反序列化消耗大 慢 22.7% 300.0 总函数个数 Ø 代码膨胀严重(2.6 x) = (越小越好) 250.0 = 全字节码缓存 VS. 部分字节码缓存 200.0 150.0 100.0 50.0 0.0 编译 运行 部分字节码缓存 总时间 全字节码缓存 首屏
11. 技术选型 调研三:缓存部分字节码(Code Cache) Code Cache Compile Run V8 Blink ExecuteScript Running Task Event Async Compile Function Event/Async/Timer/… Code Cache V8 (U4 内核) 版本的碎片化 CPU 架构通用性 机型通用性 Close Bytecode
12. 技术选型 面临的主要难题 有效性 兼容性
13. 方案设计
14. 方案设计 保证 AOT 的 有效性
15. 方案设计 保证有效性 策略一:追求极致的性能 —— PGO (Profile-guided optimization) 仅为需要被执行的函数生成代码。 函数信息收集 (移动端预发布) Source Code AST Bytecode Run 上报 函数信息 函数信息处理 (服务端) { } 合并 & 简化 函数修复 运行详情 { "s": 12, // 函数起始 "e": 26 // 函数终止 } AOT 生成 函数信息 Source Code AST AOT "name": "foo", // 函数名 "start": 12, // 函数起始 "end": 26, // 函数终止 "count": 1, // 运行次数
16. 方案设计 保证有效性 策略二:追求便捷的使用 —— 先验规则 预测需要被执行的函数。 function foo() { /* ... */ } function bar() { function inner() { return (x, y) => { return x + y; } } return inner(); } var Test = { "a": function() { /* ... */ }, "b": function() { return () => { return "hello"; } }, } 嵌套越深,使用率越低 特征 JS 越小,运行覆盖度越高 l 小型 JS:不生成 策略 l 中型 JS:全字节码缓存(覆盖度 >80%) l 大型 JS:Top 3 层 l 运行后增量更新
17. 方案设计 保证 AOT 的 兼容性
18. 方案设计 保证兼容性 策略一:在线生成 (空闲时预热) UI 线程 预热 打开页面 Blink 主线程 AOT 线程 JS 执行 framework1.js framework2.js Load Save AOT UI Task Blink Task AOT Task 生成时机: • APP 空闲时 • 后台线程 影响或不足: • 资源浪费(磁盘 & CPU) 适用场景: • 框架 JS,不经常变动
19. 方案设计 保证兼容性 策略一:在线生成 (访问时生成) 生成时机: • 页面打开时 • 后台线程 UI 线程 打开页面 Blink 主线程 网络/解析/排版/渲染 JS 执行 预热 AOT 线程 bundle1.js bundle2.js Save UI Task Blink Task Load AOT AOT Task 影响或不足: • 可能来不及 适用场景: • 业务 JS,已经离线到本地
20. 方案设计 保证兼容性 策略二:离线生成 线下 函数信息/先验规则 Source Code 线上 离线工具 AST 内置 AOT 适用场景: • APP冷启动时执行(没有预热时机) • 不经常变动 • 不需要动态更新 影响或不足: • 更新 U4 内核后,可能需同步更新 AOT AOT Run l Full Code Cache l Function.prototype.toString() 丢弃 JS 源码?
21. 方案设计 AOT 总览 移动端 Source Code AST Bytecode Run 上报 预发布 服务端 函数信息 合并 & 简化 函数修复 内置/下发 函数详情 更新完善 函数信息 线上 预热 先验规则 AST 服务端离线工具 AOT Source Code 正式 AOT Run
22. 优化效果
23. 优化效果 正常访问 (无 AOT) 打开时预热生成 AOT (先验规则) 生成 AOT JS 执行 JS 执行 Wall: 799.5 ms CPU: 726.4 ms Wall: 523.1 ms CPU: 465.6 ms PGO 49.0% ↑ 先验规则 33.9% ↑ (TOP 30+ 站点平均) JS 执行时间减少 35%
24. 夸克高考首屏性 能提升 17.6% 无 AOT 使用 AOT
25. 展 望
26. 展 望 U4 3.0 & 4.0 JavaScript Source Code Parser Abstract Syntax Tree U4 5.0 Ignition TurboFan Bytecode Optimized Machine Code TurboFan Sparkplug Unoptimized Machine Code JS 性能 ~20% ↑
27. Thanks “U4 内核技术”公众号

Home - Wiki
Copyright © 2011-2024 iteam. Current version is 2.137.1. UTC+08:00, 2024-11-16 12:07
浙ICP备14020137号-1 $Map of visitor$