摘要:注意本文是我們的性能分析系列的第三篇,點此閱讀性能分析第一篇介紹,或性能分析第二篇深入研究。小的性能提升很可能來自優化,而非緩存。注意此更改已提交到并已獲更新。目前,兩者具備相同的特性,只有一些部分重命名了。
注意:本文是我們的 PHP 性能分析系列的第三篇,點此閱讀?PHP 性能分析第一篇: XHProf & XHGui 介紹?,或??PHP 性能分析第二篇: 深入研究 XHGui 。
在本系列的 第一篇 中,我們介紹了 XHProf 。而在 第二篇 中,我們深入研究了 XHGui UI, 現在最后一篇,讓我們把 XHProf /XHGui 的知識用到工作中!
性能調優不用運行的代碼才是絕好的代碼。其他只是好的代碼。所以,性能調優時,最好的選擇是首先確保運行盡可能少的代碼。
OpCode 緩存
首先,最快且最簡單的選擇是啟用 OpCode 緩存。OpCode 緩存的更多信息可以在?這里?找到。
在上圖,我們看到啟用 Zend OpCache 后發生的情況。最后一行是我們的基準,也即沒有啟用緩存的情況。
在中間行,我們看到較小的性能提升,以及內存使用量的大幅減少。小的性能提升(很可能)來自 Zend OpCache 優化,而非 OpCode 緩存。
第一行是優化和 OpCode 緩存后結果,我們看到很大的性能提升。
現在,我們看看 APC 之前和之后的變化。如上圖所示,跟 Zend OpCache 相比,隨著緩存的建立,我們看到初始(中間行)請求的性能下降,在消耗時長與內存使用量方面的表現都明顯下降。
接著,隨之 opcode 緩存的建立,我們看到類似的性能提升。
內容緩存
第二件我們能做的事是緩存內容——這對 WordPress 而言小菜一碟。它提供了許多安裝簡便的插件來實現內容緩存,包括 WP Super Cache。WP Super Cache 會創建網站的靜態版本。該版本會在出現諸如評論事件時依照網站設置自動過期。(例如,在非常高負載情況下,您可能會想禁止任何原因造成的緩存過期)。
內容緩存只能在幾乎沒有寫操作時有效運行,寫操作會使緩存失效,而讀操作不會。
你也應該緩存應用從第三方 API 處收到的內容,從而減少由于 API 可用性導致的延遲與依賴。
?
WordPress 有兩個緩存插件,可以大大提高網站的性能:?W3 Total Cache?和?WP Super Cache。
這兩個插件都會創建網站的靜態 HTML 副本,而不是每次收到請求時再生成頁面,從而壓縮響應時間。
如果你正在開發自己的應用程序,大多數框架都有緩存模塊:?
Zend Framework 2:ZendCache
Symfony 2:Multiple options
Laravel 4:Laravel Cache
ThinkPHP 3.2.3:ThinkPHP??Cache
查詢緩存
另一個緩存選項是查詢緩存。針對 MySQL,有一個通用的查詢緩存幫助極大。對于其他數據庫,將查詢結果集緩存在 Memcached 或者 cassandra 這樣的內存緩存,也非常有效。
跟內容緩存一樣,查詢緩存在包含大量讀取操作的場景是最有效的。由于少量的數據改動就會使大塊的緩存區無效,尤其不能在這種情況下依賴 MySQL 查詢緩存來提高性能。
查詢緩存或許在生成內容緩存時對性能有提升。
如下圖所示,當我們開啟查詢緩存后,實際運行時間減少了 40% ,盡管內存使用量沒有明顯改變。
現有三種類型的緩存選項,由 query_cache_type 控制設置。
設置值為 0 或 OFF 將禁用緩存
設置值為 1 或 ON 將緩存除了以 SELECT SQL_NO_CACHE 開頭之外的所有選擇
設置值為 2 或 DEMAND 只會緩存以 SELECT SQL_CACHE 開頭的選擇
此外,你應該將 query_cache_size 設置為非零值。將它設置為零將禁用緩存,不管 query_cache_type 是否設置。
想得到設置緩存的幫助,與許多其他性能相關的設置,請查看?mysql-tuning-primer?腳本。
MySQL 查詢緩存的主要問題是,它是全局的。對緩存結果集構成的表格的任何更改都將導致緩存失效。在寫入操作頻繁的應用程序中,這將使緩存幾乎無效。
然而,你還有許多其他選擇,可以根據你的需求和數據集建立更多的智能緩存,例如?Memcached?,?riak?,?cassandra?或?redis
查詢優化
如前所述,數據庫查詢常常是程序執行緩慢的原因,查詢優化往往能比代碼優化帶來更多切身的好處。
查詢優化有助于生成內容緩存時提高性能,而且,在無法緩存這種最壞的情況下也有益處。
除了分析, MySQL 還有一個幫助識別慢查詢的選擇——慢查詢日志。慢查詢日志會記錄所有耗時超過指定時間的查詢,以及不使用索引的查詢(后者為可選項)。
您可以在 my.cnf 中使用以下配置啟用日志。
[mysqld] log_slow_queries =/var/log/mysql/mysql-slow.log? long_query_time =1 log-queries-not-using-indexes
任何查詢如果慢于 long_query_time (以秒為單位),該查詢就會記錄到日志文件 log_slow_queries 中。默認值是10秒,最低1秒。
此外, log-queries-not-using-indexes 選項可以將任何不使用索引的查詢捕獲到日志中。
之后我們可以用與 MySQL 捆綁在一起的 mysqldumpslow 命令檢查日志。
在 WordPress 安裝時使用這些選項 ,主頁加載完成并運行后得到如下數據:?
$ mysqldumpslow -g "wp_" /var/log/mysql/mysql-slow.log Reading mysql slow query log from /var/log/mysql/mysql-slow.log Count: 1??Time=0.00s (0s) Lock=0.00s (0s) Rows=358.0(358), user[user]@[host] SELECT option\_name, option\_value FROM wp_options WHERE autoload ="S" Count: 1 Time=0.00s (0s) Lock=0.00s (0s) Rows=41.0(41), user[user]@[host] SELECT user\_id, meta_key, meta_value FROM wp_usermeta WHERE user_id IN (N)
首先,注意所有字符串值都以 S 表示,數字則以 N 表示。你可以添加 -a 標志來顯示這些值。?
接下來,請注意,這兩個查詢均耗時 0.00 s,這意味著他們的耗時在 1 秒的閾值以下,且沒有使用索引。
在 MySQL 控制臺 使用 EXPLAIN,可以檢查性能下降的原因:
????mysql> EXPLAIN SELECT option_name, option_value FROM wp_options WHERE autoload = "S"G ????*************************** 1. row *************************** ???????????????id: 1 ??????select_type: SIMPLE ????????????table: wp_options ?????????????type: ALL ????possible_keys: NULL ??????????????key: NULL ??????????key_len: NULL ??????????????ref: NULL ?????????????rows: 433 ????????????Extra: Using where
此處,我們看到 possible_keys 是 NULL,從而確認未使用索引。
EXPLAIN 是對優化 MySQL 查詢非常強大的工具,更多信息可以在?這里?找到。
PostgreSQL 同樣也包括一個 EXPLAIN (該 EXPLAIN 與 MySQL 的差別很大),而 MongoDB 有$explain 元 操作符。
代碼優化
通常只有當你不再受到 PHP 本身限制(通過使用 OpCode 緩存),緩存了盡可能多的內容,優化了查詢之后,才可以開始調整代碼。
代碼和查詢優化帶來足夠的性能提升才能創建其他緩存;代碼在最糟糕的環境(沒有緩存)下性能越高,應用就越穩定,重建緩存的速度也就越快。
讓我們看看如何(潛在地)優化我們的 WordPress 安裝。
首先,讓我們看看最慢的函數:?
令我驚訝的是,列表中的第一項 不是 MySQL (事實上 mysql_query() 是第四),而是 apply_filter() 函數。
WordPress 代碼庫的特點是,通過基于事件的過濾系統執行多種數據轉換,執行次序按照數據經內核、插件添加或回調的順序。
apply_filter() 函數是這些回調應用的地方。
首先,你可能會注意到,函數被調用 4194 次。如果我們點擊查看更多細節,就可以按照“調用次數”降序排列“父函數”,從而發現 translate() 調用了__apply_filter()__ 函數 778 次。
這很有趣,因為實際上我不使用任何翻譯。我(并懷疑大多數用戶)在使用 WordPress 軟件時都設置為本土語言:英語。
因此,讓我們點擊查看細節,進一步查看該 translate() 函數在做什么。
在這里,我們看到兩間有趣的事。首先,在父函數中,有一個被調用了773次:__()。
查看該函數的源代碼后,我們發現它是 translate() 的包裝器。
????
根據經驗法則,函數調用代價昂貴,應該盡量避免。現在我們總是調用 __() 而不是 translate() ,我們應該把別名改為 translate() 來保持向后兼容性,而 __() 則不再調用非必要的函數。
然而,實際上,這種改變不會帶來多大的差異,只是微觀的優化罷了——但它的確提高了代碼可讀性,簡化了調用圖。
繼續前進,讓我們看看子函數:
現在,深入該函數,我們看到有 3 個 函數或方法被調用,每個 778 次:
get_translations_for_domain()
NOOP_Translations::translate()
apply_filters()
按照包容性實際運行時間降序排列,我們看到 apply_filter() 是目前為止耗時最長的調用。
查看代碼:
????translate( $text ), $text, $domain ); ????} ?????>
這段代碼的作用是檢索一個翻譯對象,然后將 $translations->translate() 的結果傳給 apply_filter() 。我們發現 $translations 是 NOOP_Translations 類的一個實例。
僅根據名稱(__NOOP__),再經代碼中的注釋證實,我們發現翻譯器實際上沒有任何動作!
????
因此,也許我們完全可以避免這種代碼!
通過在代碼上進行小規模調試,我們看到當前使用的是默認的域,我們可以修改代碼以忽略翻譯器:
????translate( $text ), $text, $domain ); ????} ?????>
接下來,我們再次分析,確保要運行至少兩次——確保所有緩存都建立,才是公平的對比!
這次運行的確更快!但是,快多少?為什么?
使用 XHGui 的比較運行這一特性就能找到答案。回到我們最初的運行,點擊右上角的 “比較此處運行” 按鈕,并從列表中選擇新的運行。
我們發現,函數調用的次數減少了3% ,包容性實際運行時間減少 9% ,包容性CPU時間減少12%!?
之后,可以按調用次數降序排列細節頁,這證實(如同我們的預期) get_translations_for_domain() 和 NOOP_Translations::translate() 函數的調用次數減少。同樣,可以確認沒有預料之外的變化發生。
30 分鐘的工作帶來9 - 12% 的性能提升,這非常可喜。這就意味著真實世界的性能收益,即便是在應用了 opcache 之后。
現在我們可以對其函數重復這個過程,直到找不到更多優化點。
注意:此更改已提交到 WordPress.org 并已獲更新。你可以在?WordPress Bug Tracker 跟蹤討論,查看實踐過程。此更新計劃包含在 WordPress 4.1 版本中。
其他工具除了出色的 XHProf/XHGui,還有一些很好的工具。
New Relic & OneAPM
New Relic?與?OneAPM? 均提供前后端性能分析;洞察后臺堆棧訊息,包括 SQL 查詢與代碼分析,前端 DOM 與 CSS 呈現,以及 Javascript 語句。__OneAPM__ 更多功能請移步 (OneAPM 在線DEMO)?
uprofiler
uprofiler?是目前還未發布的 Facebook XHProf 分支,該分支計劃刪除 Facebook 所需的 CLA。目前,兩者具備相同的特性,只有一些部分重命名了。
XHProf.io
XHProf.io?是 XHProf 的另一種用戶界面。XHProf.io 在配置文件存儲使用 MySQL ,用戶友好性方面不及 XHGui。
Xdebug
在 XHProf 出現之前,Xdebug?早已存在——Xdebug 是一種主動的性能分析器,這意味著它不應該用于生產環境,但可以深入了解代碼。
然而,它必須與另一個工具配合使用以讀取分析器的輸出 , 比如?KCachegrind)。但是 KCachegrind 很難安裝在非 linux 機器上。另一個選擇是?Webgrind。
Webgrind 無法提供 KCachegrind 的那些特性,但它是一個 PHP Web 應用程序,在任何環境都易于安裝。
若搭配 KCachegrind ,你可以輕易探索并發現性能問題。(事實上,這是我最喜歡的剖析工具!)
結語分析和性能調優是非常復雜的工程。有了對的工具,并理解如何善用這些工具,我們可以很大程度地提高代碼質量——即使是對我們不熟悉的代碼庫。
花時間去探索和學習這些工具是絕對值得的。
注意:本文是我們的 PHP 性能分析系列的第三篇,閱讀?PHP 性能分析第一篇: XHProf & XHGui 介紹?,和??PHP 性能分析第二篇: 深入研究 XHGui 。(本文系應用性能管理領軍企業 OneAPM 工程師編譯整理)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/21174.html
摘要:前言這是國外知名博主撰寫的應用性能分析系列的第二篇,第一篇介紹,第三篇則關注于性能調優實踐。單個性能頁面展示了相當多的信息。該頁面顯示兩個重要圖表。 【前言】這是國外知名博主 Davey Shafik 撰寫的 PHP 應用性能分析系列的第二篇,第一篇介紹 Xhprof/Xhgui,第三篇則關注于性能調優實踐。 在第一篇中,我們初步介紹了 xhprof,以及如何安裝和運行分析器。在本文,...
摘要:這是多處理器系統中,調度器用來分散任務到不同的機制,通常也被稱為處理器間中斷,。文章編寫計劃 待完成: 詳細介紹用到的各個工具 作者: 萬千鈞(祝星) 適合閱讀人群 文中的調優思路無論是php, java, 還是其他任何語言都是用. 如果你有php使用經驗, 那肯定就更好了 業務背景 框架及相應環境 laravel5.7, mysql5.7, redis5, nginx1.15 cento...
摘要:這是多處理器系統中,調度器用來分散任務到不同的機制,通常也被稱為處理器間中斷,。文章編寫計劃 待完成: 詳細介紹用到的各個工具 作者: 萬千鈞(祝星) 適合閱讀人群 文中的調優思路無論是php, java, 還是其他任何語言都是用. 如果你有php使用經驗, 那肯定就更好了 業務背景 框架及相應環境 laravel5.7, mysql5.7, redis5, nginx1.15 cento...
摘要:注這是我們應用性能分析系列的第一篇,閱讀第二篇可深入了解,第三篇則關注于性能調優實踐。性能分析的行為也會影響應用性能。主動被動性能分析主動分析器在開發過程中使用,由開發人員啟用。它對性能的影響最小,同時收集足夠的信息用于診斷性能問題。 注:這是我們 PHP 應用性能分析系列的第一篇,閱讀第二篇可深入了解 xhgui,第三篇則關注于性能調優實踐。 什么是性能分析? 性能分析是衡量應用程...
閱讀 837·2021-11-18 10:07
閱讀 2354·2021-10-14 09:42
閱讀 5315·2021-09-22 15:45
閱讀 584·2021-09-03 10:29
閱讀 3462·2021-08-31 14:28
閱讀 1873·2019-08-30 15:56
閱讀 3038·2019-08-30 15:54
閱讀 994·2019-08-29 11:32