在php 5.4的更新list上, 有一句: 提公升了zend引擎的效能, 減少了記憶體占用.
那麼, 到底是怎麼提公升的呢?
我們知道在php中, 類的屬性/靜態屬性/常量, 都是儲存在hashtable中的, 而在以前, 即使乙個類沒有申明屬性/靜態屬性/常量, zend引擎也會為他們分配hashtable.
而在現在, 這個過程被優化了, 只有在有元素的時候才會分配hashtable.
這樣就避免一些emalloc/efree操作, 減少一些記憶體占用.
在php中, 真正執行的是opcodes, 乙個opcodes包含3個固定的運算元, result, left, right, 在以前, 這三個運算元每乙個都包含乙個zval, 即使根本用不到的時候, 比如沒有右運算元的時候, 還會為右運算元分配乙個zval.
而在現在, 所有的運算元將不再直接包含zval, 而是包含乙個literal table的指標, 每乙個op array都會包含乙個literal table.
並且znode也做了相應的調整.
這樣一來, 也能減少一些記憶體占用. 從之前的(32位作業系統)乙個opcode占用72byte, 到現在的28byte.
另外, 對於string, literal table還會儲存乙份這個string的預先計算的hash值, 避免了在執行時多次計算. 從而提高一部分效能.
就好像c語言中, **中的字面字串, 會儲存在乙個固定段內(資料段), 在整個執行時期, 這些字串都是常量字串,不能被修改,不能被free.
php也借鑑了這樣的思想, 提出乙個internal string的概念, 在php**中的字面量字串, 將會一次分配, 並前在整個執行期都不能被修改.
php在copy_zval, free zval等操作的時候, 會對internal string特別處理, 避免不必要的free和複製.
並且這些字面量字串的hash值將會被預先計算, 這樣一來, 對於字串比較 ==, 以及hashtable中的hash計算來說, 都可以直接使用這個預先計算的hash值, 從而能提高一部分效能.
當然, 還有很多優化點, 比如優化了opcode, 減少了一些不必要的opcodes, 在此就不一一贅述了.
下面是php開發小組內部測試的一些資料:
原生php, 沒有opcode cache:
php-trunk
patched
inprovement
bench.php (sec)
4.31
3.49
19%micro_bench.php (sec)
19.78
14.63
26%
一些實際的應用:
php-trunk
pathced
improvement
blog (req/sec)
59.3
66.2
12%drupal (req/sec)
1073.9
1084.8
1%fw (req/sec)
105.3
111.8
6%hello (req/sec)
5362.5
5351.4
0%qdig (req/sec)
243.4
253.7
4%typo3 (req/sec)
355.3
382.6
8%wordpress (req/sec)
101.8
108.5
7%xoops (req/sec)
70.3
78.5
12%scrum (req/sec)
86.5
104.2
20%
從這些資料來看, 效能提公升還是很明顯的..
Zend引擎的優化
在php 5.4的更新list上,有一句 提公升了zend引擎的效能,減少了記憶體占用.那麼,到底是怎麼提公升的呢?我們知道在php中,類的屬性 靜態屬性 常量,都是儲存在hashtable中的,而在以前,即使乙個類沒有申明屬性 靜態屬性 常量,zend引擎也會為他們分配hashtable.而在現在...
PHP核心 Zend引擎
在前面的章節介紹了php的生命週期,php的sapi,sapi處於php整個架構較上層,而真正指令碼的執行主要由zend引擎來完成,這一小節我們介紹php指令碼的執行。目前程式語言可以分為兩大類 但它們並不是真的直接就被能被機器理解,機器只能理解機器語言,那這些語言是怎麼被執行的呢,一般這些語言都需...
PHP核心 Zend引擎
在前面的章節介紹了php的生命週期,php的sapi,sapi處於php整個架構較上層,而真正指令碼的執行主要由zend引擎來完成,這一小節我們介紹php指令碼的執行。目前程式語言可以分為兩大類 但它們並不是真的直接就被能被機器理解,機器只能理解機器語言,那這些語言是怎麼被執行的呢,一般這些語言都需...