自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

PHP操作碼:無需重構(gòu)代碼即可提高應(yīng)用程序性能

譯文 精選
開發(fā) 前端
本文介紹一些語法技巧,可以自動優(yōu)化PHP代碼執(zhí)行性能,而無需進(jìn)行復(fù)雜的重構(gòu)。

譯者 | 李睿

審校 | 重樓

PHP引擎生成的PHP操作碼深受編寫代碼方式的影響,這不僅僅體現(xiàn)在完成任務(wù)所需的語句數(shù)量上。其次,代碼的語法可能完全改變生成的操作碼,從而導(dǎo)致服務(wù)器的CPU在執(zhí)行完全相同的代碼時(shí)會產(chǎn)生大量開銷。

在過去的幾年,SaaS產(chǎn)品有了巨大的增長,提供了越來越深入優(yōu)化技術(shù)的機(jī)會,以盡可能高效地運(yùn)行工作負(fù)載。得出的結(jié)果令人印象深刻,可以幫助開發(fā)人員釋放現(xiàn)金流,以繼續(xù)SaaS之旅。

在目前SaaS產(chǎn)品的案例中,其PHP進(jìn)程每天在一臺擁有2個(gè)vCPU和8GB內(nèi)存的服務(wù)器上處理12億個(gè)以上數(shù)據(jù)包。并且使用AWS自動擴(kuò)展組,以便在不可預(yù)測的峰值情況下具有更大的靈活性,但很少使用第二臺服務(wù)器(每周一兩次)。

什么是PHP操作碼?

PHP操作碼指的是PHP引擎在編譯完開發(fā)人員編寫的PHP源代碼后執(zhí)行的低級指令。

在PHP中,代碼編譯是在運(yùn)行時(shí)runtime發(fā)生的:基本上,當(dāng)PHP引擎首次獲取代碼時(shí),它會將其編譯成這種機(jī)器友好的代碼,緩存(這樣引擎就不會再次編譯相同的代碼),然后執(zhí)行。

下圖是這個(gè)過程的簡單表示:

PHP操作碼緩存

緩存PHP操作碼允許開發(fā)人員在執(zhí)行代碼的過程中節(jié)省三個(gè)步驟:解析原始PHP代碼、標(biāo)記化和編譯。

一旦為代碼首次生成了操作碼,它就會存儲在內(nèi)存中,以便在后續(xù)請求中重復(fù)使用。這減少了PHP引擎每次執(zhí)行相同PHP代碼時(shí)都需要重新編譯的需求,從而節(jié)省了大量CPU和內(nèi)存的開銷。

PHP中最常用的操作碼緩存是OPCache,從PHP 5.5到最近的版本默認(rèn)包含了OPCache。其效率高,并得到了廣泛支持。

緩存預(yù)編譯的腳本字節(jié)碼需要在每次部署后使緩存失效。這是因?yàn)椋绻暮蟮奈募诰彺嬷杏凶止?jié)碼版本,PHP將繼續(xù)運(yùn)行舊版本的代碼,直到清除操作碼緩存,因此將再次編譯新代碼,生成新的緩存項(xiàng)。

如何調(diào)查PHP操作碼

為了理解不同的語法如何影響腳本的操作碼,需要獲取PHP引擎生成的編譯代碼的方法。

有兩種方法可以獲得操作碼。

OPCache原生函數(shù)

如果在服務(wù)器上啟用了OPCache擴(kuò)展,則可以使用其原生函數(shù)獲取特定PHP文件的操作碼:

PHP 
 // Force compilation of a script
 opcache_compile_file(__DIR__.'/yourscript.php');

 // Get OPcache status
 $status = opcache_get_status();

 // Inspect the script's entry in the cache
 print_r($status['scripts'][__DIR__.'/yourscript.php']);

VLD(Vulcan邏輯反匯編器)PHP擴(kuò)展

VLD是一個(gè)流行的PHP擴(kuò)展,它可以反匯編編譯后的PHP代碼并輸出操作碼。它是了解PHP如何解釋和執(zhí)行代碼的強(qiáng)大工具。在安裝之后,可以使用帶-d選項(xiàng)的PHP命令運(yùn)行一個(gè)啟用VLD的PHP腳本:

Shell 
 php -d vld.active=1 -d vld.execute=0 yourscript.php

輸出將包括有關(guān)編譯后的操作碼的詳細(xì)信息,包括每個(gè)操作及其相關(guān)的代碼行等等。

使用3v4l(EVAL的縮寫)

3v4l是一個(gè)非常有用的在線工具,它允許開發(fā)人員查看其在編輯器中輸入的PHP代碼生成的操作碼。它基本上是一個(gè)安裝了VLD的PHP服務(wù)器,因此它可以獲取VLD輸出并在瀏覽器中顯示操作碼。

由于它是免費(fèi)的,將在以下的分析中使用這個(gè)在線工具。

如何生成高效的PHP操作碼

3v4l非常適合理解使用的代碼語法如何以的方式影響生成的PHP操作碼。以下開始將下面的代碼粘貼到3v4l中。保持配置為“所有支持的版本”,然后單擊“eval”。

PHP 
 <?php

 namespace App;

 strlen('ciao');

在執(zhí)行代碼后,底部將出現(xiàn)一個(gè)選項(xiàng)卡菜單。導(dǎo)航到VLD選項(xiàng)卡以可視化相應(yīng)的操作碼。

Shell 
 line #* E I O op fetch ext return operands
 -------------------------------------------------------------------------------------
  5 0 E > INIT_NS_FCALL_BY_NAME 'App%5CSpace%5Cstrlen'
 1 SEND_VAL_EX 'ciao'
 2 DO_FCALL 0 
 3 > RETURN 1

需要注意的是,第一個(gè)操作是INIT_NS_FCALL_BY_NAME。解釋器使用當(dāng)前文件的名稱空間構(gòu)造函數(shù)的名稱,但在 App\Example 命名空間中并不存在這個(gè)函數(shù)——那么它是如何工作的呢?

解釋器將檢查該函數(shù)是否存在于當(dāng)前命名空間中。如果不存在,它會嘗試調(diào)用相應(yīng)的核心函數(shù)。

在這里有機(jī)會告訴解釋器避免這種雙重檢查,并直接執(zhí)行核心函數(shù)。

嘗試在strlen之前添加反斜杠(\),并單擊“eval”:

PHP 
 <?php

 namespace App;

 \strlen('ciao');

在VLD選項(xiàng)卡中,現(xiàn)在只需一條語句即可看到操作碼。

line #* E I O op fetch ext return operands
 ------------------------------------------------------------------------------------- 5 0 E > > RETURN 1

因?yàn)閭鬟_(dá)了函數(shù)的確切位置,所以不需要考慮任何回退。

如果不喜歡使用反斜杠,可以像從根命名空間導(dǎo)入其他類一樣導(dǎo)入該函數(shù):

PHP 
 <?php

 namespace App;

 use function strlen;

 strlen('ciao');

利用自動操作碼優(yōu)化

PHP引擎還有很多內(nèi)部自動化功能,可以提前生成優(yōu)化的操作碼,對靜態(tài)表達(dá)式進(jìn)行求值。這是PHP自7.x版本以來性能顯著提高的最重要原因之一。

了解這些動態(tài)可以真正減少資源消耗并降低成本。在進(jìn)行這項(xiàng)研究之后,已經(jīng)開始在整個(gè)代碼中使用這些技巧。

以下展示一個(gè)使用PHP常量的示例。在3v4l中運(yùn)行這個(gè)腳本:

PHP 
 <?php

 namespace App;

 if (PHP_OS === 'Linux') {
 echo "Linux";
 }

查看PHP操作碼的前兩行內(nèi)容:

line #* E I O op fetch ext return operands
 ------------------------------------------------------------------------------------- 5 0 E > FETCH_CONSTANT ~0 'App%5CPHP_OS' 1 IS_IDENTICAL ~0, 'Linux' 2 > JMPZ ~1, ->4 6 3 > ECHO 'Linux' 7 4 > > RETURN 1

FETCH_CONSTANT嘗試從當(dāng)前名稱空間獲取PHP_OS的值,它將查找全局名稱空間,因?yàn)樗诖颂幉淮嬖?。然后,IS_IDENTICAL指令執(zhí)行IF語句。

現(xiàn)在嘗試將反斜杠添加到常量中:

PHP 
 <?php

 namespace App;

 if (\PHP_OS === 'Linux') {
 echo "Linux";
 }

正如在操作碼中看到的那樣,引擎不需要嘗試獲取常量,因?yàn)槠湮恢矛F(xiàn)已明確,并且作為一個(gè)靜態(tài)值,它已經(jīng)被存儲在內(nèi)存中。

此外,IF語句消失了,因?yàn)镮S_IDENTITCAL語句的另一端是一個(gè)靜態(tài)字符串('Linux'),因此IF可以標(biāo)記為“true”,而無需在每次執(zhí)行時(shí)解釋它。

這凸顯了開發(fā)人員在PHP代碼的最終性能上可以產(chǎn)生的重要影響。

結(jié)論

希望這是一個(gè)有趣的話題。正如在文章開頭提到的那樣,開發(fā)人員通過使用這種策略獲得了很多好處,事實(shí)上,它們也在軟件包中使用。

可以在這里看到一個(gè)示例,說明如何在PHP包中使用這些技巧來優(yōu)化其性能。

原文標(biāo)題:PHP Opcode: Improve Application Performance Without Changing Your Code,作者:Valerio Barbera


責(zé)任編輯:華軒 來源: 51CTO
相關(guān)推薦

2022-07-04 17:32:12

DevOpsAIOps

2009-07-29 11:33:14

ASP.NET技巧ASP.NET應(yīng)用程序

2010-02-04 09:41:03

Android應(yīng)用程序

2017-06-13 17:23:53

存儲緩存數(shù)據(jù)

2011-07-07 09:03:12

ASP.NET

2009-07-01 18:24:59

JSP應(yīng)用程序JMeter

2019-10-17 10:10:23

優(yōu)化Web前端

2020-04-10 09:05:40

iOS功能代碼

2011-08-08 13:35:50

Web應(yīng)用WANWeb應(yīng)用程序

2010-11-15 16:20:33

Oracle系統(tǒng)優(yōu)化

2014-12-16 09:35:13

DevOps

2021-08-18 09:37:51

數(shù)據(jù)庫移動應(yīng)用程序

2011-09-20 10:41:45

Web

2011-03-14 09:35:26

LAMP調(diào)優(yōu)方法

2011-01-19 11:10:50

程序交付優(yōu)化應(yīng)用程序性能管理監(jiān)控

2020-12-03 08:00:00

SQL數(shù)據(jù)庫MySQL

2009-01-08 19:14:37

服務(wù)器應(yīng)用程序SQL Server

2009-12-23 10:29:01

WPF應(yīng)用程序

2012-11-28 11:09:28

IBMdW

2010-07-28 09:25:41

jQueryJavaScript性
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號