编译原理&HHVM技术分享

作者介绍了一般编译的基本原理(词法分析,语法分析,语义分析等等),既包括理论,也包括大量的实践代码示例,从而揭露影响程序执行性能的关键因素,最后才谈到PHP的性能瓶颈,以及为什么要有HHVM这样的优化,以及他们的优化方法和手段。一句话,动态语言的性能会有极大问题,需要用静态语言的方式来熟悉PHP,会得到更好的运行时优化。
展开查看详情

1.编译原理 & HHVM 关于 PHP 性能优化的一些思考 ……

2.编译原理 自从 1957 年第一门高级编程语言 Fortran 诞生以来,编译理论已经过了多年的发展,但构建编译器的流程从当年到现在并未发生太大变化。

3.词法分析 这一阶段所进行的工作:将源代码字符串转换为 token 流 所利用的模型:有限状态自动机 (NFA 、 DFA) 本质上就是 使用正则表达式匹配出源代码中所包含 的有特定含义的单词符号,即 token 那么首先,为什么要做词法分析? NFA :非确定性有限状态自动机 DFA :确定性 有限状态自动机

4.词法分析

5.词法分析

6.词法分析

7.词法分析 举一个简单的例子: DFA 如何识别浮点数常量? 这是 LeetCode 上面的一道 Hard 级别 题目 我们以浮点数 -5.141e6 为例来分析这个 DFA 的工作原理

8.Cool Things 假设我们在某个工作场景中,需要写一个自动分析大量日志文本,从中提取出指定字符串的程序 —— 显然,可以直接上正则表达式引擎。 但如果用到的正则基本不变,那么我们完全可以把 DFA 硬编码到程序中。 那么如何构造针对某条正则的 DFA 呢? —— Flex : The Fast Lexical Analyzer

9.Cool Things 什么是 Flex ? —— 它可以用于生成词法分析器,但从更广泛的意义来看,它是在生成 DFA 。 那么 Flex 如何生成先前所述的那个识别浮点数的 DFA ? 使用规则: WHITE " "| | | | %% {WHITE}*[+-]?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))([ Ee ][+-]?[0-9]+)?{WHITE}* {return true;} . {return false;} %%

10.Cool Things

11.Cool Things 参考链接: http:// blog.finaltheory.info/research/Flex-Tricks.html

12.语法分析 定义:按照 源语言的语法规则,从词法分析的结果中识别出相应的语法范畴。 本质上 就是 Parsing -> AST (抽象语法树 ) 理论基础: LALR(1) 文法、自底向上分析 也就是说,将先前词法分析所产生的 token 流,转换为有序的树状结构。 那么这样做有什么用呢?它其实是对代码文本的解析,理解其中的语法含义,从而使得程序能够针对文本的含义来进行操作。

13.语法分析 抽象语法树: while b ≠ 0 if a > b a := a − b else b := b − a return a

14.语法分析

15.语法分析 事实上,语法分析( P arsing )技术结合词法分析,可以应用于绝大多数需要分析文本的地方。 这些技术会涉及到非常复杂且 Dirty 的理论,但在实际工作中这些理论并没有什么卵 用,因为有自动化的 工具 ——Bison 来帮 我们完成这些工作。 我们以表达式求值为例,来演示一下如何使用 Bison 生成简单的语法解析器。 目标:解析形如“ ( 6.+ 2 / 3 * 5e2 )/6.5 ”的表达式

16.Cool Things 数据结构中, 我们使用双栈算术表达式求 值的方法来完成这个任务; 但我们同样可以使用 Bison 来生成一个语法分析器,代码要简洁且通用得多; 首先进行词法分析:

17.Cool Things LALR(1) 文法: statement ::= expression expression ::= expression + expression expression – expression expression * expression expression / expression - expression ( expression ) Number

18.Cool Things LALR(1) 文法: statement ::= expression expression ::= expression + expression expression – expression expression * expression expression / expression - expression ( expression ) Number

19.Cool Things LALR(1) 文法: statement ::= expression expression ::= expression + expression expression – expression expression * expression expression / expression - expression ( expression ) Number

20.语义分析 语义分析 的任务是对结构上正确的源程序进行上下文有关性质的审查 ,即进行 类型审查 。 简而言之,它需要尽可能地推导出所有变量的类型,并检查类的继承关系、重复定义等等。 编译器后端的优化已经被研究了几十年,可以说非常成熟了, PHP 性能差的主要因素就是因为它是动态语言,类型推导的效果很差。 这一点将在后面进行深入探讨,我们首先分析,类型推导是怎么进行的。

21.语义分析 类型推导与检查,本质上是一个沿着 AST 自顶向下进行深度优先遍历的过程。 此处以静态类型的语言为例: myVariable : Int = 3*5*x

22.语义分析 那么类型信息是如何提升程序运行速度的:

23.Cool Things 由于动态语言的灵活性,我们可以通过操作 AST 实现一些“奇葩”的功能。 比如这个 fuckit.py : 这个模块的大致作用是可以作为函数、类、控制流的 decorator ,或者用来导入 module ,强行消除所有的异常、报错等等。 下面来演示一下它实现了什么效果。

24.Cool Things 由于动态语言的灵活性,我们可以通过操作 AST 实现一些“奇葩”的功能。 比如这个 fuckit.py : 这个模块的大致作用是可以作为函数、类、控制流的 decorator ,或者用来导入 module ,强行消除所有的异常、报错等等。 下面来演示一下它实现了什么效果。

25.Cool Things 由于动态语言的灵活性,我们可以通过操作 AST 实现一些“奇葩”的功能。 比如这个 fuckit.py : 这个模块的大致作用是可以作为函数、类、控制流的 decorator ,或者用来导入 module ,强行消除所有的异常、报错等等。 下面来演示一下它实现了什么效果。

26.PHP 的性能瓶颈 动态类型 动态绑定

27.PHP 的性能瓶颈 动态名称创建 / 引用 / 查询 动态成员变量

28.PHP 的性能瓶颈 以及最可怕的万恶之源 —— eval() 它使得整个程序的运行时状态更加无法确定 动态语言一时爽,类型推导火葬场!

29.Zend 的缺陷 动态装载 只有当文件被 include 时, Zend 才会将其中的组件(函数、类、变量、常量)载入各个运行时“查找表” 动态查找 程序运行过程中的 所有 标识符都被放到运行时“查找表”中进行增加、修改、删除,带来巨大的额外开销 动态类型 在执行操作时, Zend 会“无脑”地做类型 检查,因为它没有做类型推导的能力,也就无法充分利用 CPU 指令