PHP 效能分析第三篇: 效能調優實戰

來源:互聯網
上載者:User
注意:本文是我們的 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:Zend\Cache

  • Symfony 2:Multiple options

  • Laravel 4:Laravel Cache

  • ThinkPHP 3.2.3:ThinkPHP Cache

查詢快取

另一個緩衝選項是查詢快取。針對 MySQL,有一個通用的查詢快取協助極大。對於其他資料庫,將查詢結果集緩衝在 Memcached 或者 cassandra 這樣的記憶體緩衝,也非常有效。

跟內容緩衝一樣,查詢快取在包含大量讀取操作的情境是最有效。由於少量的資料改動就會使大塊的緩衝區無效,尤其不能在這種情況下依賴 MySQL 查詢快取來提高效能。

查詢快取或許在產生內容緩衝時對效能有提升。

如所示,當我們開啟查詢快取後,實際已耗用時間減少了 40% ,儘管記憶體使用量量沒有明顯改變。

現有三種類型的緩衝選項,由 query_cache_type 控制設定。

  • 設定值為 0OFF 將禁用緩衝

  • 設定值為 1ON 將緩衝除了以 SELECT SQL_NO_CACHE 開頭之外的所有選擇

  • 設定值為 2DEMAND 只會緩衝以 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 =1log-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.logReading mysql slow query log from /var/log/mysql/mysql-slow.logCount: 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 工程師編譯整理

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.