茫茫網海中的冷日
         
茫茫網海中的冷日
發生過的事,不可能遺忘,只是想不起來而已!
 恭喜您是本站第 1729870 位訪客!  登入  | 註冊
主選單

Google 自訂搜尋

Goole 廣告

隨機相片
IMG_00054.jpg

授權條款

使用者登入
使用者名稱:

密碼:


忘了密碼?

現在就註冊!

PHP特區 : [轉貼]PHP 效能調校:最佳化你的php程式碼的訣竅

發表者 討論內容
冷日
(冷日)
Webmaster
  • 註冊日: 2008/2/19
  • 來自:
  • 發表數: 15773
[轉貼]PHP 效能調校:最佳化你的php程式碼的訣竅

PHP 效能調校:最佳化你的php程式碼的訣竅

最近工作內容主要就是PHP的效能調校(performance tuning),除了看《php cookbook》,《programming php》裡都有一些相關的主題外,也上網找了一些文章和工具,其中不乏精譬的討論串,但其中整理的很好的個人覺得應屬以下這一篇( http://reinholdweber.com/?p=3),個人也稍稍地加上一點心得補充,所以應該一定會超過原文的四十點。

工具上可以善用xdebug和PEAR::Benchmark、APD等工具來量測效能是否真的有被調到。如果要做壓力測試可以用ab(Apache HTTP server benchmarking tool)和 http_loadJMeter。另外,好的apache server組態設定和DB schema和index設計也很重要,總之,要調出好的performance除了程式撰寫上的風格和技巧外,有更多其它週邊相關的技術需求,也需要做不少的實驗來量測數據,一個系統需要調校的是整體,而不是部份的程式碼就可以達到全面性的成果,至於要調到什麼地步,套句老子的話:「 知足不辱,知止不怠」,如此而已。

好在我工作上,公司中有一堆大俠相助(Frank, Winson, Chary, hermit, James 先謝囉!),還可以渡過這回的小小難關,希望我淺薄的實戰經驗和小小心得也可以幫到別人。


最佳化你的php程式碼的訣竅


  • 如果method可以是static,那就宣告它為static。速度的改善可以是4倍。
  • echo 比 print 快多了。
  • 使用echo的多個參數用法,不要用string的串接(jiing: 也就是用逗號,不要用句號)
  • 在迴圈之前設定你的for迴圈的極大值,不要在迴圈中
  • Unset你的變數來釋放記憶體,尤其是大型陣列
  • 避免使用magic 函式,像是 __get, __set, __autoload
  • require_once()非常昂貴(jiing:能用require就用require,儘可能不要重覆require_once或include_once)
  • 在includes和requires中使用完整的路徑,會花費較少的時間在解析OS路徑。
  • 當script已經開始時,如果如果你需要找出時間(time),$_SERVER['REQUEST_TIME'] 要比time()好的多。
  • 看看你是否能用 strncasecmp, strpbrk 和 stripos 來取代regex(jiing:如果可以用字串相關函數來取代正規表示式,那麼就試試看,有時候多個幾行反而比較快)作法:搜尋所有的(用find指令) preg_exp , preg_match相關指令,並研究如何用str相關的函式來取代
  • str_replace比 preg_replace快,不過strstr又比str_replace快四倍
  • 如果函式(例如字串取代函式),同時接受array和單一字元作為引數,且你的引數串接不是太長,考慮撰寫一些多餘的置換陳述式,一次傳遞一個字元,不要寫一行程式碼來作為搜尋和取代引數、接受陣列。(jiing:意思是寧可多寫幾行來做這件事)
  • 用switch陳述式會比多個if else if 好的多。
  • switch中,常跑的case放前面一點也會gain到一點效能。
  • 用@來做錯誤抑制非常慢
  • 打開apache的 mod_deflate
  • 當你完成資料庫相關操作時,關閉你的資料庫連結
  • $row['id']要比$row[id] 要快上七倍
  • 錯誤訊息非常昂貴
  • 在for迴圈中不要使用函式,例如:for ($x=0; $x < count($array); $x)
  • count()函式會每次都被呼叫。
  • 一般而言for會比foreach快,但當迴圈裡的元素(element)大時,有時foreach會稍快一些(個人的心得是要作實驗)
  • 在method中遞增local變數是最快的。幾乎和呼叫函式中的一個local變數一樣快。
  • 遞增一個global變數比local變數慢二倍。
  • 遞增一個object property(e.g., $this->prop++)會比local 變數慢上三倍。
  • 遞增一個未定義的local變數會比一個預先初始化的變數慢上9-10倍
  • 只宣告一個global變數,而沒有在函式中使用它也會讓事情變慢(大約與遞增local變數的時間一樣)。php可能會去做檢查來看看全域(global)變數是否存在。
  • 方法呼叫似乎與class內所定義的方法數目不相干,因為我新增十多個方法到test class(在test method之前和之後),在效能上並沒有變化。
  • 在子class的method執行的比在母class定義的更快。
  • 具有一個參數和一個空函式主體的函式呼叫花費大約是7-8個$localvar++運算一樣多的時間。
  • 相似的方法呼叫當然約是15個$localvar++運算一樣多的時間。
  • 以單引號括住字串會比以雙引號(")括住字串快一丁點,因為php會對"..."查找變數,而不會對'...'。(jiing:少寫含糊不清的雙引號(""),是字串就用單引號)當然囉,只當你在字串中沒有變數時,才可以這麼做。
  • 儘量減少型別轉換和判斷
  • 當使用echo來列印字串時,使用逗號來分隔字串會比用句號(.)快一點。
  • 注意:這只要對echo有用,echo是個函式,它可以採取數個字串作為引數(arguments)。
  • 使用php 快取的產品。(jiing:如 xcache, php_apc,也可以考慮架設squid等proxy server,, db能開多大的cache就開上去)
  • 快取多多益善。 用 memcached
  • 可以用isset()來取代stelne($str)==0

  • Ex.
    if (strlen($foo) < 5) { echo "Foo is too short"; }
    vs.
    if (!isset($foo{5})) { echo "Foo is too short"; }
  • 在php裡++$i,比$i++快一點
  • 不需要每件事都OOP,通常它是過度負載(overhead),每個method和物件呼叫花費很多的記憶體。(jiing:效能和可維護性、可擴充性的取捨真難啊.......orz)
  • 不要實作每個資料結構成class,array也很有用
  • 不要過度切分method,思考,哪些程式碼是你真的將會重覆使用的
  • 當有需要時,你總是可以稍後再切分一個method的程式碼
  • 善用數不盡的內定(predefined)函式(jiing:也有例外,hash('md5','optimize this')比md5('optimize this')快)
  • 如果有一堆字串結合後不斷輸出的動作,可以考慮使用ob_start()相關的函式
  • 如果你有非花費時間的函式的程式碼裡,那麼考慮寫C的extension。(jiing:PECL裡有相關文件,敝公司中據說有V Ving大神留下來的程式碼可以參考,目前祈禱不要用到這個大絕招)


原文出處:jiing's blog - PHP 效能調校:最佳化你的php程式碼的訣竅
冷日
(冷日)
Webmaster
  • 註冊日: 2008/2/19
  • 來自:
  • 發表數: 15773
[轉貼]PHP 加速器的調校(php-eaccelerator)
PHP - PHP 加速器的調校(php-eaccelerator)
php-eaccelerator 官方網站: http://www.eaccelerator.net/

由於 PHP 屬於直譯語言,因此當放在 Web 伺器器上的 PHP 程式碼被瀏覽者所讀取時,系統為了要執行 PHP 程式碼就必須要使用直譯器(interpreter),將 PHP 程式碼翻譯成電腦系統看得懂(或可以執行)的語言。這個直譯的動作是非常耗費系統資源的,而直譯語言的特性偏偏就是每次執行前都要先進行直譯的動作,因此當您放在 Web 伺服器上的 PHP 程式碼被 1000 個 client 讀取時,系統就要進行 1000 次的直譯動作。而 PHP 加速器的功能就是會把被這些 PHP 程式碼快取(Cache)起來,也就是同一支程式碼只要被直譯一次而已,藉此大幅降低系統的負載。自己個人的經驗是:若你的 Web 伺服器流量非常大,有沒有使用 PHP 加速器會有非常大的差別。

php-eaccelerator 的安裝很容易,但麻煩的是後續的調整。一般來講,若你會需要安裝加速器通常就代表你遇上了效能的瓶頸,也就是系統負載過大所以才需要安裝它;但是 php-eaccelerator 有 BUG,當系統負載過大,php-eaccelerator 需要消除 Share Memory 中的老舊資料時,會導致 apache 出現如下的錯誤訊息並使 CPU 使用率衝上 100%,最後終將致使伺服器當機。

引用:

[Wed Feb 28 14:39:40 2007] [notice] child pid 18449 exit signal Segmentation fault (11)
就是因為負載過高才需要裝它,偏偏負載過高裝了它又會造成伺服器當機,很矛盾不是嗎?所幸經過適當的調整後,即可避免上述的情況發生。php-eaccelerator 的安裝很容易,這裡就不多做說明,至於設定則是要修改 php-eaccelerator 的系統設定檔(/etc/php.d/eaccelerator.ini),設定完後請記得重新啟動 Web 伺服器。
引用:

/etc/php.d/eaccelerator.ini:
zend_extension="/usr/lib/php/modules/eaccelerator.so"
eaccelerator.shm_size = "500"
==>預設是32MB,這裡設為500MB

eaccelerator.cache_dir = "/var/cache/php-eaccelerator"
eaccelerator.enable = "1"
eaccelerator.optimizer = "0"
==>預設是 1 (開啟),這裡設為 0 (關閉)

eaccelerator.debug = "0"
eaccelerator.log_file = "/var/log/httpd/eaccelerator_log"
eaccelerator.name_space = ""
eaccelerator.check_mtime = "1"
eaccelerator.filter = ""
eaccelerator.shm_max = "0"
eaccelerator.shm_ttl = "0"
==>預設是3600,這裡設為0,也就是不移除Share Memory中的任何資料。

eaccelerator.shm_prune_period = "0"
eaccelerator.shm_only = "0"
eaccelerator.compress = "1"
eaccelerator.compress_level = "9"
eaccelerator.keys = "shm_and_disk"
eaccelerator.sessions = "shm_and_disk"
eaccelerator.content = "shm_and_disk"


大致上要注意的有以下幾點:
  1. 調高php-eaccelerator可使用的Share Memory大小:
    eaccelerator.shm_size = "500"
    .
  2. 關閉最佳化功能
    eaccelerator.optimizer = "0"
    .
  3. 禁止php-eaccelerator清除Share Memory中的資料:
    eaccelerator.shm_ttl = "0"
    eaccelerator.shm_prune_period = "0"
    .
  4. 每日定時清除cache資料與Share Memory,並重新啟動httpd。
    新增 /etc/cron.daily/restart_httpd:
    /sbin/service httpd stop
    rm -rf /var/cache/php-eaccelerator/*
    /sbin/service httpd start

原文出處: 史萊姆論壇 - PHP - PHP 加速器的調校(php-eaccelerator)
前一個主題 | 下一個主題 | 頁首 | | |



Powered by XOOPS 2.0 © 2001-2008 The XOOPS Project|