PHP7新特性
php7.x增加的新特性介紹可以參考這里:
https://www.runoob.com/php/php7-new-features.html
https://php.net/manual/zh/migration70.new-features.php
php7.x版本系列相比之前的php的版本提交性能提高了不少,下圖是wordpress在不同php版本下的壓力測試表現。
這里面其中的一些主要改變是性能提高的關鍵,主要有以下內容。
1.zval使用棧內存
在zend引擎和擴展中,經常要創建php變量,其底層就是一個zval指針,之前的php版本都是通過MAKE_STD_ZVAL動態的從堆內存上分配一個zval內存。而php7直接使用棧內存,好處是少了一次內存分配。php程序中回大量創建變量,所以php7會在棧上預分配一塊內存來存放這些zval,來節省大量的內存分配和管理操作。
php5
zval *val ; MAKE_STD_ZVAL(val)
php7
zval val;
2.zend_string存儲hash值,array查詢不再需要重復計算hash
數組是php比較重要的數據結構,php程序中會有大量的array關聯查詢,雖然hashtable查找的復雜度是O(1),但是key的值每次要轉化成一個hash值,需要用一個復雜的hash函數去計算的,這樣就會占用cpu時間,不過不光數組,在php底層很多地方都會用到hashtable,比如類的屬性方法函數等。其實php程序運行起來大部分key的值是不變的,所以php7就保存了這些hash值下次直接使用,那么php7就為字符串單獨創建了新類型叫做zend_string,除了char*指針和長度之外,增加了一個hash字段,用於保存字符串的hash值,數據鍵值查找不再反復需要計算hash值。為了優化數組的鍵值查找。
上圖代碼中 zend_ulong h;就是存儲hash值。
3.hashtable桶內直接存放數據,減少了內存申請次數,順便也提升了cache命中率和訪問速度。因為指針不是連續的是分布在不同的內存頁上,如果讀取第一個或者第三個桶,它們的數據可能會在兩個頁上。
php7之前
數據存放是在上圖arBuckets這個結構體上,存放了一些bucket * 指針,指針上就是對應了一些數據。php7對這些做了一些改進,如下圖。
php7
php7將之前arBuckets改成了上圖中的arData,而這個arData直接就是一個大塊內存,這個內存上面就是一個個桶bucket,這樣的好處就是每次數據就不需要動態去申請內存。
4.zend_parse_parameters改為宏實現,性能提升15%。
5.新增加4種opcode,call_user_function(),is_int(),is_string(),is_array(),strlen(),defined() 4個函數變為php opcode指令,速度更快。
6.PHP7 的內核中有一個重要的變化是加入了 AST(Abstract syntax tree)抽象語法樹,指代碼在計算機內存的一種樹狀數據結構,樹上的每個節點都表示源代碼中的一種結構,便於計算機理解和解析。
在 PHP5系列版本中,從 php 腳本到 opcodes 的執行的過程如下:
-
詞法掃描分析(Lexing):將源文件轉換成 token 流;
-
語法分析(Parsing):生成 op arrays。
PHP7 中在語法分析階段先生成 AST:
-
詞法掃描分析(Lexing):將源文件轉換成 token 流。
-
語法分析(Parsing):從 token 流生成抽象語法樹。
-
Compilation:從抽象語法樹生成 op arrays。
這個表達式($a)['b'] = 1
就會被解析成下圖這樣的一棵樹結構
7.其他更多性能優化,如基礎類型 float , int , bool等改成直接進行值拷貝。排序算法改進了,PCER with JIT , execute_data和opline使用全局寄存器,使用gdb4.8的PGO功能。
8.php7與JIT
最初HHVM退出一個很重要的特性就是JIT,JIT就是just in time的縮寫,表示運行時候將指令轉換成二進制機器碼,我們知道C和C++是將源代碼編譯然后生成二進制機器碼去執行的,而php,python等腳本語言是將源代碼轉換成中間指令然后在vm(虛擬機)上執行,另外java系語言他們使用的JVM引擎底層也是JIT,是將java的字節碼編譯成二進制的機器碼去執行的。對於計算密集型的的程序,JIT可以將PHP的opcode直接轉換成機器碼,可以大幅度提升PHP性能。
不過PHP7.0-final版本中不會帶有JIT特性的。
但是
為什么php7版本沒有使用JIT呢?
是因為php官方之前有個php中間版本是帶有JIT的,后來php官方開發組使用JIT測試時候發現JIT對於實際項目的性能沒有太大的性能提升,所以最終放棄使用JIT方案。但后來發現密集計算性的php程序使用JIT后性能還會大幅提升。
PHP7下載與安裝
1.第一步 下載源代碼
wget https://www.php.net/distributions/php-7.2.21.tar.bz2
2.第二步 解壓源代碼 tar -xjvf php-7.2.21.tar.bz2
3.第三步 進入目錄 cd php-7.2.21
4.第四步 執行configure shell腳本檢測環境及配置php安裝目錄 比如檢測php安裝是否必須要有gcc 和 authconfig等工具 ./configure --prefix=/usr/local/src/php7
出現下面提示說明上面執行成功
Generating files configure: creating ./config.status creating main/internal_functions.c creating main/internal_functions_cli.c +--------------------------------------------------------------------+ | License: | | This software is subject to the PHP License, available in this | | distribution in the file LICENSE. By continuing this installation | | process, you are bound by the terms of this license agreement. | | If you do not agree with the terms of this license, you must abort | | the installation process at this point. | +--------------------------------------------------------------------+ Thank you for using PHP. 5.第五步 編譯安裝 make && make install
出現下面提示說明make成功
clicommand.inc
directorygraphiterator.inc
invertedregexiterator.inc
pharcommand.inc
phar.inc
Build complete.
Don't forget to run 'make test'.
出現下面提示說明make install成功
Installing PEAR environment: /usr/local/src/php7/lib/php/
[PEAR] Archive_Tar - installed: 1.4.7
[PEAR] Console_Getopt - installed: 1.4.2
[PEAR] Structures_Graph- installed: 1.1.1
[PEAR] XML_Util - installed: 1.4.3
[PEAR] PEAR - installed: 1.10.9
Wrote PEAR system config file at: /usr/local/src/php7/etc/pear.conf
You may want to add: /usr/local/src/php7/lib/php to your php.ini include_path
/usr/local/src/php-7.2.21/build/shtool install -c ext/phar/phar.phar /usr/local/src/php7/bin
ln -s -f phar.phar /usr/local/src/php7/bin/phar
Installing PDO headers: /usr/local/src/php7/include/php/ext/pdo/
驗證php安裝成功
songguojundeMBP:php7 songguojun$ pwd /usr/local/src/php7 songguojundeMBP:php7 songguojun$ ls bin etc include lib php var songguojundeMBP:php7 songguojun$ cd bin/ songguojundeMBP:bin songguojun$ ./php -v #顯示php版本 下面打印出php版本說明php安裝成功 PHP 7.2.21 (cli) (built: Feb 22 2019 22:19:32) ( NTS ) Copyright (c) 1997-2018 The PHP Group Zend Engine v3.1.0, Copyright (c) 1998-2018 Zend Technologies
如果php命令找不到就添加到啟動文件中
songguojundeMBP:~ songguojun$ vim ~/.bash_profile alias ll='ls -alF' alias la='ls -A' export PATH="/usr/local/opt/libiconv/bin:$PATH" alias php=/usr/local/src/php7/bin/php
songguojundeMBP:~ songguojun$ source ~/.bash_profil
源碼安裝可能會出現的問題:
1. 缺少libiconv提示
checking for iconv support... yes checking for iconv... no checking for libiconv... no configure: error: Please specify the install prefix of iconv with --with-iconv=<DIR>
下載libiconv庫
brew install libiconv