php性能的問題


一.影響php性能的常見原因

1.php自身語法使用不當

2.php做了不擅長的時期()

3.php的周邊環境(服務器Linux,磁盤:文件存儲,數據庫,緩存:內存,網絡:帶寬)

4.php自身的短板

5.未知問題

二、分析

PHP代碼運行流程 
*.php(PHP文件)->Scanner(掃描代碼,分析)->Exprs(保存成zend引擎可以識別的文件)->Parser(解析)->Opcodes(能被執行的文件)->Exec(執行)->Output(輸出結果)

 

1.php語言級的性能優化。指的是PHP語法基本功能,這部分優化比較簡單易見、快速可行,比較快速看到效果。

1.1  少寫PHP的代碼,多用PHP自身能力解決問題

性能問題

自寫代碼冗余較多,可讀性不佳,並且性能低,如代碼很長很長...PHP代碼越長PHP的執行效率越慢。

     為什么性能低?

PHP代碼需要解析編譯為C語言,底層C語言又要編譯成匯編語言機器語言才能執行,這個過程在每次請求過來之后都要處理一遍,所以開銷很大(項目變大的話...)。

     解決方法:

多使用PHP內置的變量、常量、函數。我們用PHP代碼實現的功能和使用PHP內置的函數實現的同樣功能差別是有的。

 1.2 PHP內置函數的性能優劣。

情況描述
PHP內置函數之間依然存在快慢差別;少用PHP魔術方法;

     建議:
     多去了解PHP內置函數的執行實現復雜度。
     測試方法:比較效率測試,如用microtime()函數,取差值,精確到毫秒級別;Linux的time命令可以查看開銷。

 

1.3 產生額外開銷的錯誤抑制符號“@”,最好別用(不管是性能優化和項目的健壯性等方面)。

    @的邏輯是在代碼前和代碼結束后增加了Opcode,Opcode的作用就是忽略報錯,其實就是相當於增加了error_reporting設置,等級報錯為忽略(vld擴展可以查看被隱藏的Opcode)

1.4 合理使用內存

    利用unset()及時釋放不使用的內存,比如一些數據庫多余字段(注意:unset()有時會出現注銷不掉的情況)

    當出現變量引用是,需要把兩個變量都unset才可以注銷內存;或者直接$變量=null來注銷

1.5 盡量少用正則表達式

    正則表達式的開銷大,使用起來簡單,但是性能低因為,正則表達式需要回溯;正則表達式越長,回溯的開銷越大,優化正則表達式是需要技術水平的,正則技術不達標,不要亂用正則。

1.6 避免在循環內做運算。

    循環內的計算式將被重復計算(我們在for循環或者while循環,會有重復計算,影響性能問題)

1.7 減少計算密集型業務

情況描述:

PHP不適合密集型(大數據量)運算的場景。

     為什么?

PHP的語言特性決定PHP不適合做大數據量運算,PHP語言由C寫的,PHP處於C基礎之上,PHP的所有運算處理流程需要轉化為C語言,PHP和C想比性能肯定輸了,並且

PHP語言還有一些環境問題、語言特性,相比於C而言的開銷要大很多的。PHP一段很長的代碼,可能C很短就實現了...

PHP適合場景:

適合銜接WebServer與后端服務,WebServer來了請求交給PHP,PHP做一些校驗、一些初始化數據處理,將請求轉發交給后端,等待后台響應,后端可能是緩存、DB等其他業務,

后端響應之后,PHP再作為紐帶,將信息傳遞給WebServer,這是PHP擅長的。PHP也擅長做UI呈現,也就是配合模板引擎做模板輸出,其實就是一些字符串文本處理。

 

1.8 務必使用帶引號字符串做鍵值(數組的Key字段)。

    PHP會將沒有使用引號的鍵值當做常量,產生查找常量的開銷,如果查找到了常量有這個字符串,那么就把常量作為這個值了。

    建議:嚴格使用引號作為鍵值,單引號即可。

1.9 盡量靜態化

   一個方法能被靜態,就聲明它為靜態的,速度可以提高1/4,

其實靜態方法和非靜態方法的效率主要區別在內存:
靜態方法在程序開始時生成內存,實例方法在程序運行中生成內存,所以靜態方法可以直接調用,實例方法要先成生實例,通過實例調用方法,靜態速度很快,但是多了會占內存
任何語言都是對內存和磁盤的操作,至於是否面向對象,只是軟件層的問題,底層都是一樣的,只是實現方法不同。靜態內存是連續的,因為是在程序開始時就生成了,而實例申請的是離散的空間,所以當然沒有靜態方法快。 靜態方法始終調用同一塊內存,其缺點就是不能自動進行銷毀,而是實例化可以銷毀。

 

 1.10   用單引號代替雙引號來包含字符串,這樣做會更快一些。因為 PHP 會在雙引號包圍的 字符串中搜尋變量,單引號則不會

1.11  echo 比 print 快,並且使用 echo 的多重參數(譯注:指用逗號而不是句點)代替字符串 連接

1.12 include 文件時盡量使用絕對路徑,因為它避免了 PHP 去 include_path 里查找文件的速 度,解析操作系統路徑所需的時間會更少

1.13  include()與require()的區別及require_once的代價

include() 遇到文件處理失敗時,會產生一個警告;

而require()則會顯示一個致命錯誤。也就是說在腳本執行過程中,如果代碼中有錯誤,include()則會忽略錯誤並繼續執行腳本,而require()則會停止腳本運行。 在php中使用require_once
/include_once雖然方便,但是代價昂貴,據測試數據來看,require_once比require慢3-4倍,所以在php開發中,我們應該盡量使用require/include。

 

1.14 foreach 效率更高,盡量用 foreach 代替 while 和 for 循環;

總體來說,如果數據庫過幾十萬了,才能看出來快一點還是慢一點,如果低於10萬的循環,就不用測試了。php推薦用foreach。
循環數字數組時,for需要事先count($arr)計算數組長度,需要引入自增變量$i,每次循環都要進行條件判斷$i<$c,然后自增$i++,輸出數組元素時,$arr[$i]需要進行哈希操作.

而foreach循環數組時,指針會自動指向下一個元素,不需要計算數組長度,沒有條件判斷和自增變量,調用元素時也沒有哈希操作,所以性能肯定要比for和while高.另外,for和while對存在鍵值映射的關聯數組無能為力.
所以,遍歷數組,首選foreach.foreach也是我PHP里最喜歡的關鍵字,因為它確實強大.array_map
/array_filter/array_walk遍歷數組的方式和foreach一樣,但需要執行回調函數,所以也比foreach慢.

2.php周邊環境的性能優化

性能排列:內存>數據庫>磁盤>網絡

2.1 減少文件的操作,操作完成要關閉文件。

2.2 

網絡優化:

  網絡原因:

   1.對方接口不確定。接口地址錯誤;數據錯誤

    2.網絡不穩定

   網絡優化:

  a.設置超時時間

   1.鏈接超時 200ms

   2.讀超時  800ms

   3.寫超時 500ms

  b.將串行請求並行化;把多次請求,放到一次請求中

    1.使用curl_multi_*()

     2.使用swoole擴展

2.3 壓縮php接口

   使用: Gzip ,php有對應壓縮和解壓的函數

   利:利於我們的數據的數據輸出,Client端能更快獲取數據

   弊:額外的cpu開銷

2.4 緩存

 對於變化少,訪問量大的數據做緩存;緩存可以減輕服務器負載、減低網絡阻塞、增強www可擴展性

  a.文件緩存

  b.memcached

  c.Redis

2.5 旁路方案

 

3.php性能的測試

3.1 使用內置函數,測試代碼執行時間;microtime()

3.2 Linux的time命令

3.3 apache測試工具,ab 可以測試並發時執行代碼所需要的時間。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM