PHP性能優(yōu)化初識


layout: post
title: "PHP性能優(yōu)化初識"
date: 2016-05-04 22:46:21 +0800
comments: true
categories: [PHP]


PHP性能優(yōu)化

一、PHP性能優(yōu)化問題解析

PHP的性能問題,占整體項目性能問題的比例不足50%,所以在考慮性能優(yōu)化項目的時候,不要局限于僅優(yōu)化PHP。

PHP的性能優(yōu)化問題的解決方向(困難度從容易到簡單)

PHP語言級的性能優(yōu)化
PHP周邊問題的性能優(yōu)化(開發(fā)環(huán)境等)
PHP語言自身分析、優(yōu)化(底層C)

壓力測試工具簡介

Apache Benchmark(ab)

簡介

ab是由Apache提供的壓力測試軟件。安裝Apache服務(wù)器時會自帶該壓測軟件。

如何使用

./ab -n1000 -c100 http://www.baidu.com (目標(biāo)網(wǎng)址)
-n 請求數(shù)
-c 并發(fā)數(shù)
url 目標(biāo)壓測地址

結(jié)果分析

主要看
Request per second 每秒接受的請求數(shù)
Time per request   一個請求的耗時

二、PHP語言級的優(yōu)化

優(yōu)化點:少寫代碼,多用PHP自身能力,多使用PHP內(nèi)置的函數(shù),變量,常量

性能問題:自寫代碼冗余較多,可讀性不佳,并且性能低

為什么性能低?

我們自己寫的代碼每次需要編譯解析成底層語言,每一次請求都會處理一遍開銷很大。

PHP內(nèi)置函數(shù)的性能優(yōu)劣

情況描述:

PHP內(nèi)置函數(shù)之間依然存在著快慢差異

多去了解PHP內(nèi)置函數(shù)的時間復(fù)雜度

舉例

<?php
    $start=current_time();
    $i=0;
    $arr=range(1,200000);
    while($i<200000){
        ++$i;
        //isset($arr[$i]); //測試結(jié)果50多ms
        array_key_exists($i,$arr); //測試結(jié)果80多ms
    }
    $end=current_time();
    echo "Lost Time:".number_format($end-$start,3)*1000;
    echo "\n";
    /**
     *返回一個微秒級別的時間戳
     */
    function current_time(){
        list($usec,$sec)=explode("",microtime());
        return ((float)$usce+(float)$sec);
    }
?> 

測試結(jié)果說明isset比array_key_exists函數(shù)更優(yōu)化。


減少PHP魔法函數(shù)的使用

情況描述:

PHP提供的魔法函數(shù)性能不佳

舉例

<?php
class test{
    private $var="123";
    public function __get($varname){
        return $this->var;
    }
}
$i=0;
while($i<10000-){
    $i++;
    $test=new test();
    $test->var;
}//大概80ms
?>
<?php
class test{
    public $var="123";
    //public function __get($varname){
        //return $this->var;
    //}
}
$i=0;
while($i<100000){
    $i++;
    $test=new test();
    $test->var;
}//大概50ms
?>

不使用魔法函數(shù),性能更優(yōu)化。

PS:

在Linux中可以使用 time php test.php
會輸出三個時間,主要關(guān)注user為執(zhí)行時間

產(chǎn)生額外開銷的錯誤抑制符@

情況描述:

@的實際邏輯是在代碼開始前結(jié)束后增加Opcode 忽略報錯。
在@這行前加入Opcode忽略報錯,又在這行結(jié)束后再加入Opcode,恢復(fù)報錯。
<?php
    file_get_contents("XXX");
    
?>

用VLD擴(kuò)展看Opcode代碼:

php -dvld.active=1 -dvld.execute=0 at.php //我們只看代碼不執(zhí)行

有三行代碼
加上@符號后
有五行代碼

建議不要使用錯誤抑制符@,
多使用try catch


合理使用內(nèi)存

情況描述:

PHP有內(nèi)存回收機(jī)制保底,但也要小心使用內(nèi)存。

利用unset()及時釋放不適用的內(nèi)存(注:unset()出現(xiàn)注銷不掉的情況)


盡量少的使用正則表達(dá)式

情況描述:

正則表達(dá)式的回溯開銷較大。

避免在循環(huán)內(nèi)做運算

情況描述:

循環(huán)內(nèi)的計算式將會被重復(fù)計算
<?php
    $str="Hello World!"
    for($i=0;$i<strlen($str);$i++){//每次循環(huán)都會計算這個字符串的長度
        //do something
    }
?>

改進(jìn):

<?php
    $str="Hello World!"
    $strlen=strlen($str)
    for($i=0;$i<$strlen;$i++){
        //do something
    }
?>

減少計算密集型業(yè)務(wù)

情況描述:

PHP的語言特性決定了PHP不適合密集型運算的場景。
因為PHP是基于C語言的,所以在處理大型運算的時候開銷是比C大很多的。

適合的場景:

銜接Webserver與后端服務(wù),UI呈現(xiàn)。

務(wù)必使用帶引號字符串做鍵值

情況描述:

PHP會將沒有引號的鍵值當(dāng)做常量,產(chǎn)生查找常量的開銷。

三、PHP周邊問題的性能優(yōu)化

Linux 運行環(huán)境

減少文件類的操作

常見PHP場景的開銷次序:

讀寫內(nèi)存<<讀寫數(shù)據(jù)庫(數(shù)據(jù)庫有內(nèi)存緩存)<讀寫磁盤<讀寫網(wǎng)絡(luò)數(shù)據(jù)(網(wǎng)絡(luò)延遲)

優(yōu)化網(wǎng)絡(luò)請求

可能的問題:
1. 對方接口的不確定因素
2. 網(wǎng)絡(luò)穩(wěn)定性

優(yōu)化:

1. 設(shè)置超時時間
    連接超時(200ms)
    讀超時(800ms)
    寫超時(500ms)
2. 串行請求并行化
    使用curl_multi_*() //取決于最長的連接時間所以不推薦
    使用swoole擴(kuò)展  

壓縮PHP接口輸出

使用Gzip壓縮即可

優(yōu)點:

利于我們的數(shù)據(jù)輸出,Client能更快獲取數(shù)據(jù)

缺點:

產(chǎn)生cpu額外開銷

可以考慮當(dāng)數(shù)據(jù)大于多少時再使用壓縮來優(yōu)化。


緩存重復(fù)計算的內(nèi)容

什么情況下:

多次請求,內(nèi)容不變 //使用模板渲染緩存 如smarty 開啟caching

重疊時間窗口思想和旁路方案

在幾個任務(wù)不強(qiáng)依賴前一個任務(wù)的輸出或者返回時??梢栽谏弦粋€任務(wù)沒完成時就執(zhí)行下一個任務(wù)

四、PHP性能分析

用XHPorf進(jìn)行PHP性能問題的具體分析

XHPorf:源自Facebook的PHP性能優(yōu)化工具
其他工具:

ab -壓力測試
vld -opcode 代碼分析

here

五、PHP性能瓶頸究極辦法

Opcode Cache : PHP擴(kuò)展APC,memcache

通過PHP擴(kuò)展代替原PHP代碼中高頻邏輯

Runtime優(yōu)化: HHVM

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容