首页 >互联网 > 内容

互联网常识:一起看看php7和PHP5对比的新特性和性能优化

互联网 2021-04-25 04:37:27

跟大家讲解下有关一起看看php7和PHP5对比的新特性和性能优化,相信小伙伴们对这个话题应该也很关注吧,现在就为小伙伴们说说一起看看php7和PHP5对比的新特性和性能优化,小编也收集到了有关一起看看php7和PHP5对比的新特性和性能优化的相关资料,希望大家看到了会喜欢。

推荐(免费):PHP7

1、抽象语法树( AST)

1)在 PHP5中从 php 脚本到 opcodes 的执行的过程是:

Lexing:词法扫描分析将源文件转换成 token 流;Parsing:语法分析在此阶段生成 op arrays。

2)PHP7 中在语法分析阶段不再直接生成 op arrays而是先生成 AST所以过程多了一步:

Lexing:词法扫描分析将源文件转换成 token 流;Parsing:语法分析从 token 流生成抽象语法树;Compilation:从抽象语法树生成 op arrays。

添加了抽象语法树:内存的使用增加了但是执行时间上却有所降低

AST在PHP编译过程作为一个中间件的角色替换原来直接从解释器吐出opcode的方式让解释器(parser)和编译器(compliler)解耦可以减少一些Hack代码同时让实现更容易理解和可维护

2、Natice TLS

PHP在多线程模式下需要解决“线程安全”(TSThread Safe)的问题因为线程是共享进程的内存空间的所以每个线程本身需要通过某种方式构建私有的空间来保存自己的私有数据避免和其他线程相互污染。

而PHP5采用的方式就是维护一个全局大数组为每一个线程分配一份独立的存储空间线程通过各自拥有的key值来访问这个全局数据组。而这个独有的key值在PHP5中需要传递给每一个需要用到全局变量的函数PHP7认为这种传递的方式并不友好并且存在一些问题。因而尝试采用一个全局的线程特定变量来保存这个key值。

3、指定参数 返回值类型

PHP语言一个非常重要的特点就是“弱类型”它让PHP的程序变得非常容易编写.

PHP7可选的方式支持类型定义,除此之外还引入了一个开关指令declare(strict_type=1);当这个指令一旦开启将会强制当前文件下的程序遵循严格的函数传参类型和返回类型。

4、zval 结构的变化

在PHP5的时候, zval的定义如下:

struct _zval_struct {
union {
long lval;
double dval;
struct {
char *val;
int len;
} str;
HashTable *ht;
zend_object_value obj;
  zend_ast *ast;
  } value;
zend_uint refcount__gc;
zend_uchar type;
  zend_uchar is_ref__gc;
};

首先这个结构体的大小是(在64位系统)24个字节, 我们仔细看这个zval.value联合体, 其中zend_object_value是最大的长板, 它导致整个value需要16个字节, 这个应该是很容易可以优化掉的, 比如把它挪出来, 用个指针代替,因为毕竟IS_OBJECT也不是最最常用的类型.

第二, 这个结构体的每一个字段都有明确的含义定义, 没有预留任何的自定义字段, 导致在PHP5时代做很多的优化的时候, 需要存储一些和zval相关的信息的时候, 不得不采用其他结构体映射, 或者外部包装后打补丁的方式来扩充zval, 比如5.3的时候新引入专门解决循环引用的GC, 它不得采用如下的比较hack的做法

第三, PHP的zval大部分都是按值传递, 写时拷贝的值, 但是有俩个例外, 就是对象和资源, 他们永远都是按引用传递, 这样就造成一个问题, 对象和资源在除了zval中的引用计数以外, 还需要一个全局的引用计数, 这样才能保证内存可以回收. 所以在PHP5的时代, 以对象为例, 它有俩套引用计数, 一个是zval中的, 另外一个是obj自身的计数:

第四, 我们知道PHP中, 大量的计算都是面向字符串的, 然而因为引用计数是作用在zval的, 那么就会导致如果要拷贝一个字符串类型的zval, 我们别无他法只能复制这个字符串. 当我们把一个zval的字符串作为key添加到一个数组里的时候, 我们别无他法只能复制这个字符串. 虽然在PHP5.4的时候, 我们引入了INTERNED STRING, 但是还是不能根本解决这个问题.

还比如, PHP中大量的结构体都是基于Hashtable实现的, 增删改查Hashtable的操作占据了大量的CPU时间, 而字符串要查找首先要求它的Hash值, 理论上我们完全可以把一个字符串的Hash值计算好以后, 就存下来, 避免再次计算等等

第五, 这个是关于引用的, PHP5的时代, 我们采用写时分离, 但是结合到引用这里就有了一个经典的性能问题:

第六, 也是最重要的一个, 为什么说它重要呢? 因为这点促成了很大的性能提升, 我们习惯了在PHP5的时代调用MAKE_STD_ZVAL在堆内存上分配一个zval, 然后对他进行操作, 最后呢通过RETURN_ZVAL把这个zval的值”copy”给return_value, 然后又销毁了这个zval, 比如pathinfo这个函数:

5、异常处理

PHP 5 的 try ... catch ... finally 无法处理传统错误如果需要你通常会考虑用 set_error_handler 来 Hack 一下。但是仍有很多错误类型是 set_error_handler 捕捉不到的

PHP 7引入 Throwable 接口错误及异常都实现了 Throwable无法直接实现 Throwable但可以扩展 \Exception 和 \Error 类。可以用 Throwable 捕捉异常跟错误。\Exception 是所有PHP及用户异常的基类;\Error 是所有内部PHP错误的基类。

$name = "Tony";
try {
    $name = $name->method;
} catch (\Error $e) {
    echo "出错消息 --- ", $e->getMessage, PHP_EOL;
}
 
try {
    $name = $name->method;
} catch (\Throwable $e) {
    echo "出错消息 --- ", $e->getMessage, PHP_EOL;
}
 
try {
    intp(5, 0);
} catch (\pisionByZeroError $e) {
    echo "出错消息 --- ", $e->getMessage, PHP_EOL;
}

6、hashtable 的变化

7、执行器

8、新的参数解析方式

PHP5 对应的参数解析 zend_parse_parament

PHP7对应的参数解析:fast_zpp

以上就是一起看看php7和PHP5对比的新特性和性能优化的详细内容!

来源:php中文网

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时候联系我们修改或删除,多谢。