天天看点

Facebook 开源 JavaScript 代码优化工具 Prepack

5月4日,facebook开源团队技术作者joel marcey在hacker news社区发布一则《prepack帮助提高javascript代码的效率》,引起了社区的广泛讨论。

官方宣称prepack是一个优化javascript源代码的工具,实际上它是一个javascript的部分求值器(partial evaluator),可在编译时执行原本在运行时的计算过程,并通过重写javascript代码来提高其执行效率。prepack用简单的赋值序列来等效替换javascript代码包中的全局代码,从而消除了中间计算过程以及对象分配的操作。对于重初始化的代码,prepack可以有效缓存javascript解析的结果,优化效果最佳。

以下五个概念可以帮助你更好地理解prepack的运行机制:

抽象语法树(ast)prepack运行在ast级别,使用babel解析并生成javascript源代码。

具体执行(concrete execution)prepack的核心是一个javascript解释器,它与ecmascript 5几乎完全兼容,而且紧密地保持与ecmascript 2016语言规范的一致性,你可以将prepack中的解释器视为完全参照javascript实现的。解释器能够跟踪并撤销包括所有对象mutation在内的结果,从而能够进行推测优化(speculative optimization)。

符号执行(symbolic execution)除了对具体值进行计算外,prepack的解释器还可以操作受环境相互作用影响的抽象值。例如date.now可以返回一个抽象值,你可以通过helper辅助函数(如__abstract())手动注入抽象值。prepack会跟踪所有在抽象值上执行的操作,在遇到分支时,prepack会执行并探索所有可能性。所以,prepack实现了一套javascript的符号执行引擎。

抽象释义(abstract interpretation)符号执行在遇到抽象值的分支时会分叉(fork),prepack会在控制流合并点加入分歧执行(diverged execution)来实现抽象释义的形式。连接变量和堆属性可能会得到条件抽象值,prepack会跟踪有关抽象值和型域(type domain)的信息。

堆序列化(heap serialization)当全局代码返回,初始化阶段结束时,prepack捕获最终的堆并按顺序排列堆栈,生成直观的javascript新代码,创建并链接初始化堆中可访问的所有对象。堆中的一些值可能是抽象值的计算结果,对于这些值,prepack将生成原始程序完成计算所执行的代码。

以下是官方提供的prepack优化示例:

prepack团队对未来的规划如下:

短期

稳定现有功能集,用于预优化(prepack)react native代码包

集成react native工具链

根据react native所用模块系统的假设来构建优化

中期

进一步优化序列化(serialization),包括:消除不暴露特性(identity)的对象;消除未使用的导出属性,等等

预优化每个函数、基本代码块、语句、表达式

与es6保持完全一致

支持广泛的模块系统

假设es6支持某些功能,延迟完成或直接忽略polyfill应用

进一步实现web和node.js环境中的兼容性目标

深入集成javascript虚拟机,改进堆反序列化过程,包括 :暴露“对象懒初始化”的概念 - 以一种javascript无感知的方式,在首次使用对象时对其进行初始化;通过专门的字节码提高普通对象创建的编码效率;将代码分为两个阶段:1) 非环境依赖阶段,虚拟机可以安全地捕获并恢复生成的堆;2)环境依赖阶段,通过从环境中获得的值执行所有剩余的计算过程来拼凑具体的堆,等等

总结循环和递归

长期 - 利用prepack作为一个平台

javascript playground - 通过调整javascript引擎体验javascript特性,这些引擎由javascript所编写,托管在浏览器中;你可以把它想象成一个“babel虚拟机”,实现了不能被编译的javascript新特性

捉bug - 发现异常崩溃、执行问题……

效果分析,例如检测模块工厂函数可能的副作用或强制纯净注释

类型分析

信息流分析

调用图推理,允许内联和代码索引

自动测试生成,利用符号执行的特性与约束求解器(constraint solver)结合来计算执行不同执行路径的输入

智能模糊(smart fuzzing)

javascript沙盒 - 以不可观察的方式有效地测试javascript代码

目前prepack仍处于早期开发阶段,尚未准备好在生产环境中使用,官方建议仅尝试使用,并欢迎提供反馈以帮助修复错误。

继续阅读