PHP7比PHP5.0 ~ 5.6快了近5倍,同时还降低了对系统资源的占用。主要是PHP7对Zend引擎进行了深度优化。
之前在书上看到过两者比较全面的区别,回头去翻了翻书【眼过千遍,不如手过一遍啊】,特记录如下。
分三个方面来比较:
0、底层优化
1、语法变化
2、性能变化
0、增加抽象语法树(AST)。
PHP5:PHP代码在语法解析阶段直接生成opline指令,执行器直接执行opline指令。
PHP7: PHP代码解析生成抽象语法树,然后将抽象语法树编译成opline指令。解耦编译器和执行器。
1、Native TLS(线程局部存储)
PHP5: 通过参数传递的方式传递本线程资源池。容易遗漏、并且及其不优雅。
PHP7: 使用Native TLS来保存线程的资源池。
2、指定函数参数、返回值类型
PHP7: 指定了函数参数和返回值类型。
注意⚠️:如果类型不一致会报error错误。尝试了不太好用,比如int和string不好分,input过来的id=1是string, 代码中是int, 需要手动转换。
3、zval结构的变化。
PHP5: refcount__gc在zval中;zval结构大小24byte。
PHP7: refcount__gc在zval的value中;zval结构大小16byte。
3.1、PHP5 zval结构
定义文件{PHPSRC}/Zend/zend.h
typedef struct _zval_struct { zvalue_value value; zend_uint refcount__gc; zend_uchar type; zend_uchar is_ref__gc; } zval; typedef union _zvalue_value { long lval; double dval; struct { char *val; int len; } str; HashTable *ht; zend_object_value obj; } zvalue_value;
3.2、PHP7 zval结构
定义文件{PHPSRC}/Zend/zend_types.h
typedef struct _zval_struct zval; struct _zval_struct { zend_value value; /* value */ union { struct { ZEND_ENDIAN_LOHI_3( zend_uchar type, /* active type */ zend_uchar type_flags, union { uint16_t extra; /* not further specified */ } u) } v; uint32_t type_info; } u1; union { uint32_t next; /* hash collision chain */ uint32_t cache_slot; /* cache slot (for RECV_INIT) */ uint32_t opline_num; /* opline number (for FAST_CALL) */ uint32_t lineno; /* line number (for ast nodes) */ uint32_t num_args; /* arguments number for EX(This) */ uint32_t fe_pos; /* foreach position */ uint32_t fe_iter_idx; /* foreach iterator index */ uint32_t access_flags; /* class constant access flags */ uint32_t property_guard; /* single property guard */ uint32_t constant_flags; /* constant flags */ uint32_t extra; /* not further specified */ } u2; }; typedef union _zend_value { zend_long lval; /* long value */ double dval; /* double value */ zend_refcounted *counted; zend_string *str; zend_array *arr; zend_object *obj; zend_resource *res; zend_reference *ref; zend_ast_ref *ast; zval *zv; void *ptr; zend_class_entry *ce; zend_function *func; struct { uint32_t w1; uint32_t w2; } ww; } zend_value;
4、异常处理
PHP7将多数错误改为异常抛出。
PHP5: 调用的方法不存在报error。
PHP7: 可通过try catch捕获,使得错误处理更加可控。
try { salmonl(); } catch (Throwable $e) { var_dump($e->getMessage); } // PHP5下运行结果 // <b>Fatal error</b>: Call to undefined function salmonl() in <b>[...][...]</b> on line <b>3</b><br /> // PHP7下运行结果 // <b>Notice</b>: Undefined property: Error::$getMessage in <b>[...][...]</b> on line <b>5</b><br />
说明:PHP7下是通过Throwable异常类来捕获的,Throwable是父类,Exception类和Error类是子类。
5、HashTable的变化。
PHP5: HashTable结构大小72tye; 数组元素Bucket结构72byte。
PHP7: HashTable结构大小56tye; 数组元素Bucket结构32byte。
6、执行器。
PHP5: 通过执行器的调度函数execute_ex()传递execute_data和opline两个变量。
PHP7: execute_data和opline通过寄存器变量存储。
7、新的参数解析方式。
PHP7: 定义2个宏包裹待解析参数。
8、语法新特性
8.0、null合并运算符
// PHP5 $id = isset($_GET['id']) ? $_GET['id'] : 0; // PHP7 $id = $_GET['id'] ?? 0;
8.1、太空船操作符
// PHP5 usort($datas, function ($a, $b) { if ($a['score'] == $b['score']) { return 0; } return ($a['score'] < $b['score']) ? 1 : -1; }); // PHP7 usort($datas, function ($a, $b) { return $b['score'] <=> $a['score']; });
8.2、define定义常量数组
// version >= 5.6 const IT = ['sina', 'baidu', 'tencent']; echo IT[0]; // version >= 7.0 define('IT', ['sina', 'baidu', 'tencent']); echo IT[0];
多版本在线测试环境:http://sandbox.onlinephpfunctions.com/
参考:
《PHP7内核剖析》
手册:PHP7新特性