發新話題

PHP的42個優化建議

PHP的42個優化建議

1.如果一個方法可靜態化,就對它做靜態聲明。速率可提升至4倍。

2.echo 比 print 快。

3.使用echo的多重參數(譯註:指用逗號而不是句點)代替字符串連接。

4.在執行for循環之前確定最大循環數,不要每循環一次都計算最大值。

5.註銷那些不用的變量尤其是大數組,以便釋放內存。

6.儘量避免使用__get,__set,__autoload。

7.require_once()代價昂貴。

8.在包含文件時使用完整路徑,解析操作系統路徑所需的時間會更少。

9.如果你想知道腳本開始執行(譯註:即服務器端收到客戶端請求)的時刻,使用$_SERVER[『REQUEST_TIME']要好於time()。

10.函數代替正則表達式完成相同功能。

11.str_replace函數比preg_replace函數快,但strtr函數的效率是str_replace函數的四倍。

12.如果一個字符串替換函數,可接受數組或字符作為參數,並且參數長度不太長,那麼可以考慮額外寫一段替換代碼,使得每次傳遞參數是一個字符,而不是只寫一行代碼接受數組作為查詢和替換的參數。

13.使用選擇分支語句(譯註:即switch case)好於使用多個if,else if語句。

14.用@屏蔽錯誤消息的做法非常低效。

15.打開apache的mod_deflate模塊。

16.數據庫連接當使用完畢時應關掉。

17.$row[『id']的效率是$row[id]的7倍。

18.錯誤消息代價昂貴。

19.儘量不要在for循環中使用函數,比如for ($x=0; $x < count($array); $x)每循環一次都會調用count()函數。

20.在方法中遞增局部變量,速度是最快的。幾乎與在函數中調用局部變量的速度相當。

21.遞增一個全局變量要比遞增一個局部變量慢2倍。

22.遞增一個對象屬性(如:$this->prop++)要比遞增一個局部變量慢3倍。

23.遞增一個未預定義的局部變量要比遞增一個預定義的局部變量慢9至10倍。

24.僅定義一個局部變量而沒在函數中調用它,同樣會減慢速度(其程度相當於遞增一個局部變量)。PHP大概會檢查看是否存在全局變量。

25.方法調用看來與類中定義的方法的數量無關,因為我(在測試方法之前和之後都)添加了10個方法,但性能上沒有變化。

26.派生類中的方法運行起來要快於在基類中定義的同樣的方法。

27.調用帶有一個參數的空函數,其花費的時間相當於執行7至8次的局部變量遞增操作。類似的方法調用所花費的時間接近於15次的局部變量遞增操作。

28.用單引號代替雙引號來包含字符串,這樣做會更快一些。因為PHP會在雙引號包圍的字符串中搜尋變量,單引號則不會。當然,只有當你不需要在字符串中包含變量時才可以這麼做。

29.輸出多個字符串時,用逗號代替句點來分隔字符串,速度更快。注意:只有echo能這麼做,它是一種可以把多個字符串當作參數的「函數」(譯註:PHP手冊中說echo是語言結構,不是真正的函數,故把函數加上了雙引號)。

30.Apache解析一個PHP腳本的時間要比解析一個靜態HTML頁面慢2至10倍。儘量多用靜態HTML頁面,少用腳本。

31.除非腳本可以緩存,否則每次調用時都會重新編譯一次。引入一套PHP緩存機制通常可以提升25%至100%的性能,以免除編譯開銷。

32.儘量做緩存,可使用memcached。memcached是一款高性能的內存對象緩存系統,可用來加速動態Web應用程序,減輕數據庫負載。對運算碼 (OP code)的緩存很有用,使得腳本不必為每個請求做重新編譯。

33. 當操作字符串並需要檢驗其長度是否滿足某種要求時,你想當然地會使用strlen()函數。此函數執行起來相當快,因為它不做任何計算,只返回在zval 結構(C的內置數據結構,用於存儲PHP變量)中存儲的已知字符串長度。但是,由於strlen()是函數,多多少少會有些慢,因為函數調用會經過諸多步驟,如字母小寫化(譯註:指函數名小寫化,PHP不區分函數名大小寫)、哈希查找,會跟隨被調用的函數一起執行。在某些情況下,你可以使用isset() 技巧加速執行你的代碼。

(舉例如下)
if (strlen($foo) < 5) { echo "Foo is too short"$$ }
(與下面的技巧做比較)
if (!isset($foo{5})) { echo "Foo is too short"$$ }

調用isset()恰巧比strlen()快,因為與後者不同的是,isset()作為一種語言結構,意味著它的執行不需要函數查找和字母小寫化。也就是說,實際上在檢驗字符串長度的頂層代碼中你沒有花太多開銷。

34. 當執行變量$i的遞增或遞減時,$i++會比++$i慢一些。這種差異是PHP特有的,並不適用於其他語言,所以請不要修改你的C或Java代碼並指望它們能立即變快,沒用的。++$i更快是因為它只需要3條指令(opcodes),$i++則需要4條指令。後置遞增實際上會產生一個臨時變量,這個臨時變量隨後被遞增。而前置遞增直接在原值上遞增。這是最優化處理的一種,正如Zend的PHP優化器所作的那樣。牢記這個優化處理不失為一個好主意,因為並不是所有的指令優化器都會做同樣的優化處理,並且存在大量沒有裝配指令優化器的互聯網服務提供商(ISPs)和服務器。

35.並不是事必面向對象(OOP),面向對象往往開銷很大,每個方法和對象調用都會消耗很多內存。

36.並非要用類實現所有的數據結構,數組也很有用。

37.不要把方法細分得過多,仔細想想你真正打算重用的是哪些代碼?

38.當你需要時,你總能把代碼分解成方法。

39.儘量採用大量的PHP內置函數。

40.如果在代碼中存在大量耗時的函數,你可以考慮用C擴展的方式實現它們。

41.評估檢驗(profile)你的代碼。檢驗器會告訴你,代碼的哪些部分消耗了多少時間。Xdebug調試器包含了檢驗程序,評估檢驗總體上可以顯示出代碼的瓶頸。

42.mod_zip可作為Apache模塊,用來即時壓縮你的數據,並可讓數據傳輸量降低80%。

TOP

英文

There are a number of tricks that you can use to squeeze the last bit
of performance from your scripts. These tricks won't make your
applications much faster, but can give you that little edge in
performance you may be looking for. More importantly it may give you
insight into how PHP internals works allowing you to write code that
can be executed in more optimal fashion by the Zend Engine. Please keep
in mind that these are not the 1st optimization you should perform.
There are some far easier and more performance advantageous tricks,
however once those are exhausted and you don't feel like turning to C,
these maybe tricks you would want to consider. So, without further
ado...

1)
When working with strings and you need to check that the string is
either of a certain length you'd understandably would want to use the
strlen() function. This function is pretty quick since it's operation
does not perform any calculation but merely return the already known
length of a string available in the zval structure (internal C struct
used to store variables in PHP). However because strlen() is a function
it is still somewhat slow because the function call requires several
operations such as lowercase & hashtable lookup followed by the
execution of said function. In some instance you can improve the speed
of your code by using a isset() trick.

Ex.
if (strlen($foo) < 5) { echo "Foo is too short"; }

vs.

if (!isset($foo{5})) { echo "Foo is too short"; }

Calling isset() happens to be faster then strlen() because unlike
strlen(), isset() is a language construct and not a function meaning
that it's execution does not require function lookups and lowercase.
This means you have virtually no overhead on top of the actual code
that determines the string's length.

2) When incrementing or decrementing the value of the variable $i++
happens to be a tad slower than ++$i. This is something PHP specific
and does not apply to other languages, so don't go modifying your C or
Java code thinking it'll suddenly become faster, it won't. ++$i happens
to be faster in PHP because instead of 4 opcodes used for $i++ you only
need 3. Post incrementation actually causes in the creation of a
temporary var that is then incremented. While pre-incrementation
increases the original value directly. This is one of the optimization
that opcode optimized like Zend's PHP optimizer. It is a still a good
idea to keep in mind since not all opcode optimizers perform this
optimization and there are plenty of ISPs and servers running without
an opcode optimizer.

3) When it comes to printing text to screen PHP has so many
methodologies to do it, not many users even know all of them. This
tends to result in people using output methods they are already
familiar from other languages. While this is certainly an
understandable approach it is often not best one as far as performance
in concerned.

print vs echo

Even both of these output mechanism are language constructs, if you
benchmark the two you will quickly discover that print() is slower than
echo(). The reason for that is quite simple, print function will return
a status indicating if it was successful or not, while echo simply
print the text and nothing more. Since in most cases (haven't seen one
yet) this status is not necessary and is almost never used it is
pointless and simply adds unnecessary overhead.

printf

Using printf() is slow for multitude of reasons and I would strongly
discourage it's usage unless you absolutely need to use the
functionality this function offers. Unlike print and echo printf() is a
function with associated function execution overhead. More over
printf() is designed to support various formatting schemes that for the
most part are not needed in a language that is typeless and will
automatically do the necessary type conversions. To handle formatting
printf() needs to scan the specified string for special formatting code
that are to be replaced with variables. As you can probably imagine
that is quite slow and rather inefficient.

heredoc

This output method comes to PHP from PERL and like most features
adopted from other languages it's not very friendly as far as
performance is concerned. While this method allows you to easily output
large chunks of text while preserving things like newlines and even
allow for variable handling inside the text block this is quite slow
and there are better ways to do that. Performance wise this is just
marginally faster then printf() however it does not offer nearly as
much functionality.

?><?

When you need to output a large or even a medium sized static bit of
text it is faster and simpler to put it outside the of PHP. This will
make the PHP's parser effectively skipover this bit of text and output
it as is without any overhead. You should be careful however and not
use this for many small strings in between PHP code as multiple context
switches between PHP and plain text will ebb away at the performance
gained by not having PHP print the text via one of it's functions or
constructs.

4) Many scripts tend to reply on regular expression to validate the
input specified by user. While validating input is a superb idea, doing
so via regular expression can be quite slow. In many cases the process
of validation merely involved checking the source string against a
certain character list such as A-Z or 0-9, etc... Instead of using
regex in many instances you can instead use the ctype
extension (enabled by default since PHP 4.2.0) to do the same. The
ctype extension offers a series of function wrappers around C's is*()
function that check whether a particular character is within a certain
range. Unlike the C function that can only work a character at a time,
PHP function can operate on entire strings and are far faster then
equivalent regular expressions.

Ex.
preg_match("![0-9]+!", $foo);

vs

ctype_digit($foo);

5) Another common operation in PHP scripts is array searching. This
process can be quite slow as regular search mechanism such as
in_array() or manuall implementation work by itterating through the
entire array. This can be quite a performance hit if you are searching
through a large array or need to perform the searches frequently. So
what can you do? Well, you can do a trick that relies upon the way that
Zend Engine stores array data. Internally arrays are stored inside hash
tables when they array element (key) is the key of the hashtables used
to find the data and result is the value associated with that key.
Since hashtable lookups are quite fast, you can simplify array
searching by making the data you intend to search through the key of
the array, then searching for the data is as simple as $value =
isset($foo[$bar])) ? $foo[$bar] : NULL;. This searching mechanism is
way faster then manual array iteration, even though having string keys
maybe more memory intensive then using simple numeric keys.

Ex.
$keys = array("apples", "oranges", "mangoes", "tomatoes", "pickles");

if (in_array('mangoes', $keys)) { ... }

vs

$keys = array("apples" => 1, "oranges" => 1, "mangoes" => 1, "tomatoes" => 1, "pickles" => 1);

if (isset($keys['mangoes'])) { ... }

The bottom search mechanism is roughly 3 times faster.

If you know or have any additional optimization tricks let me know -).

TOP

發新話題

本站所有圖文均屬網友發表,僅代表作者的觀點與本站無關,如有侵權請通知版主會盡快刪除。