首頁  >  文章  >  後端開發  >  一起看看php7和PHP5對比的新特性和效能優化

一起看看php7和PHP5對比的新特性和效能優化

coldplay.xixi
coldplay.xixi轉載
2021-02-04 09:13:072506瀏覽

一起看看php7和PHP5對比的新特性和效能優化

推薦(免費):PHP7

1、抽象語法樹( AST)

   1)在PHP5中,從php 腳本到opcodes 的執行的過程是:

  1. # Lexing:詞法掃描分析,將原始檔轉換成token 流;
  2. Parsing:語法分析,在此階段產生op arrays。

2)PHP7 中在語法分析階段不再直接產生op arrays,而是先生成AST ,所以過程多了一步:

  1. Lexing:詞法掃描分析,將原始檔轉換成token 流;
  2. Parsing:語法分析,從token 流產生抽象語法樹;
  3. Compilation:從抽象語法樹產生op arrays。

加入了抽象語法樹:記憶體的使用增加了,但是執行時間上卻有所降低

AST在PHP編譯過程中作為一個中間件的角色,取代原來直接從解釋器吐出opcode的方式,讓解釋器(parser)和編譯器(compliler)解耦,可以減少一些Hack程式碼,同時,讓實作更容易理解和可維護

#2、Natice TLS

 

#PHP在多執行緒模式下,需要解決「執行緒安全」(TS,Thread 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中文網其他相關文章!

陳述:
本文轉載於:csdn.net。如有侵權,請聯絡admin@php.cn刪除