2009年11月10日 星期二
優化PHP執行效率的40條技巧
1.如果一個方法能被靜態,那就聲明他為靜態的,速度可提高1/4;
2.echo的效率高於print,因為echo沒有返回值,print返回一個整型;
3.在循環之前設置循環的最大次數,而非在在循環中;
4.銷毀變量去釋放內存,特別是大的數組;
5.避免使用像__get, __set, __autoload等魔術方法;
6.requiere_once()比較耗資源;
7.在includes和requires中使用絕對路徑,這樣在分析路徑花的時間更少;
8.如果你需要得sexinsex到腳本執行時的時間,$_SERVER['REQUSET_TIME']優於time();
9.能使用字符處理函數的,儘量用他們,因為效率高於正則;
10.str_replace字符替換比正則替換preg_replace快,但strtr比str_replace又快1/4;
11.如果一個函數既能接受數組又能接受簡單字符做為參數,例如字符替換,並且參數列表不是太長,可以考慮多用一些簡潔的替換語句,一次只替換一個字符,而不是接受數組做為查找和替換參數。大事化小,1+1>2;
12.用@掩蓋錯誤會降低腳本運行速度;
13.$row['id']比$row[id]速度快7倍,建議養成數組鍵加引號的習慣;
14.錯誤信息很有用;
15.在循環裡別用函數,例如For($x=0; $x < count($array); $x), count()函數在外面先計算;
16.在方法裡建立局部變量速度最快,97xxoo幾乎和在方法裡調用局部變量一樣快;
17.建立一個全局變量要比局部變量要慢2倍;
18.建立一個對象屬性(類裡面的變量)例如($this->prop++)比局部變量要慢3倍;
19.建立一個未聲明的局部變量要比一個初始化的局部變量慢9-10倍;
20.聲明一個未被任何一個函數使用過的全局變量也會使性能降低(和聲明相同數量的局部變量一樣),PHP可能去檢查這個全局變量是否存在;
21.方法的性能和在一個類裡面定義的方法的數目沒有關係,因為我添加10個或多個方法到測試的類裡面(這些方法在測試方法的前後)後性能沒什麼差異;
22.在子類裡方法的性能優於在基類中;
23.只調用一個參數並且函數體為空的函數運行花費的時間等於7-8次$localvar++運算,而一個類似的方法(類裡的函數)運行等於大約15次$localvar++運算;
24.Surrounding your string by 『 instead of 」 will make things interpret a little faster since php looks for variables inside 「…」 but not inside 『…』. Of course you can only do this when you don't need to have variables in the string.
25.當輸出字符串時用逗號代替點分割更快些。注意:這只對echo起作用,這個函數能接受一些字符串作為參數;
26.在apache服務器裡一個php腳本頁面比相應的HTML靜態頁面生成至少要多花2-10倍的時間,建議多用些靜態HTML頁面和少量的腳步;
27.除非你的安裝了緩存,不然你的php腳本每次被訪問都需要被重編譯。建議安裝個php緩存程序,這樣通過去除一些重複的編譯來很明顯的提高你20-100%的性能;
28.建議用memcached,高性能的分佈式內存對象緩存系統,提高動態網絡應用程序性能,減輕數據庫的負擔;
29.使用ip2long()和long2ip()函數把IP地址轉成整型存放進數據庫而非字符型。這幾乎能降低1/4的存儲空間。同時可以很容易對地址進行排序和快速查找;
30.使用checkdnsrr()通過域名存在性來確認部分email地址的有效性,這個內置函數能保證每一個的域名對應一個IP地址;
31.如果你在使用php5和mysql4.1以上的版本,考慮使用mysql_*的改良函數mysqli_*;
32.試著喜歡使用三元運算符(?:);
33.在你想在徹底重做你的項目前,看看PEAR有沒有你需要的。PEAR是個巨大的資源庫,很多php開發者都知道;
34.使用highlight_file()能自動打印一份很好格式化的頁面源代碼的副本;
35. 使用error_reporting(0)函數來預防潛在的敏感信息顯示給用戶。理想的錯誤報告應該被完全禁用在php.ini文件裡。可是如果你在用一個共享的虛擬主機,php.ini你不能修改,那麼你最好添加error_reporting(0)函數,放在每個腳本文件的第一行(或用 require_once()來加載)這能有效的保護敏感的SQL查詢和路徑在出錯時不被顯示;
36.使用 gzcompress() 和gzuncompress()對容量大的字符串進行壓縮(解壓)在存進(取出)數據庫時。這種內置的函數使用gzip算法能壓縮到90%;
37.通過參數變量地址得引用來使一個函數有多個返回值。你可以在變量前加個「&」來表示按地址傳遞而非按值傳遞;
38.Fully understand 「magic quotes」 and the dangers of SQL injection. I'm hoping that most developers reading this are already familiar with SQL injection. However, I list it here because it's absolutely critical to understand. If you've never heard the term before, spend the entire rest of the day googling and reading.
39.使用strlen()因為要調用一些其他操作例如lowercase和hash表查詢所以速度不是太好,我們可以用isset()來實現相似的功能,isset()速度優於strlen();
40.When incrementing or decrementing the value of the variable $i++ happens to be a tad slower then ++$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.
2009年7月29日 星期三
PHP cURL 中 CURLOPT_CONNECTTIMEOUT 和 CURLOPT_TIMEOUT 的關聯
PHP cURL 有兩個 option - CURLOPT_CONNECTTIMEOUT 和 CURLOPT_TIMEOUT ,在 PHP: curl_setopt - Manual 的介紹分別是︰
CURLOPT_CONNECTTIMEOUT
The number of seconds to wait whilst trying to connect. Use 0 to wait indefinitely.
CURLOPT_TIMEOUT
The maximum number of seconds to allow cURL functions to execute.
我看完在想的是,那這兩個 option 彼此之間有沒有關係?會不會互相影響?
順手測了一下,答案是會。
CURLOPT_TIMEOUT 要比 CURLOPT_CONNECTTIMEOUT 大,不然設定 CURLOPT_CONNECTTIMEOUT 就沒有意義了。 CURLOPT_TIMEOUT 設定的秒數一到,就算 CURLOPT_CONNECTTIMEOUT 設定的秒數還沒到, cURL 也會被強制中斷。
我測試的方法是設定 CURLOPT_URL 連往不存在的 IP 。設定連往不存在的 Domain 沒法測,因為 cURL 去 DNS 查不到 IP 就不會繼續跑了,還用不到 CURLOPT_CONNECTTIMEOUT 和 CURLOPT_TIMEOUT 。
(PHP)判斷字串是否為中文
$str="hi";
if (mb_strlen($str,"Big5") == strlen($str))
return "不是中文";
else
return "此字串為中文";
2009年7月15日 星期三
將傳送到php的form資料還原回html格式
語法 :
string nl2br
(string string)
說明 :
在所有的新行(newline)前面插入'參考 : htmlspecialchars( ) htmlentities( ) wordwrap( )
',此函式傳回一字串。
2009年6月16日 星期二
php 設定時區
putenv("TZ=Asia/Taipei");
只要把這一行指令加到所建置的首頁上,系統時間就會被設定為台灣時區。
而且只要執行一次即可,下次要執行就等系統時間被設成別的時區or系統重置之後了。
2009年6月1日 星期一
php 和 asp 對等的語法
1)寫HTML
asp: Response.Write(str)
php: print $str;
echo $str;
print_r $debug_str;
2) Form, Cookie and QueryString變量
asp: 可以用Request object.
php: 這些變量是自動提供的作為一個全局變量,如果在PHP.ini文件中這樣配置的話:
variables_order="EGPCS"
register_globals=On
為了安全,我將不允許register_globals (設置它為OFF). 然後變量僅僅在數組中使用:
$HTTP_POST_VARS, $HTTP_COOKIE_VARS and $HTTP_GET_VARS.
3)Redirecting to another location
asp: Response.Redirect(url)
php: Header("Location: $url");
4) Cookie 處理
asp: Response.Cookies(cookiename) = newval
avar = Request.Cookies(cookiename)
php: setcookie($cookiename, $newval);
$avar = $HTTP_COOKIE_VARS[$cookiename];
5)Application變量
asp: Application(appvarname)
php: 不提供,可以用數據庫模擬
6)Session 變量
asp: Session(sessionname) = newval
avar = Session(sessionname)
php: 在PHP4或以後的版本中, 我們確定變量作為一個session在
session_register($sessionname), 然後,我們調用session_start( )
在開始使用的.php 頁恢復session變量值.
例如:
session_register("avar");
$avar = 99;
session_start();
print $avar;
7)Form 變量
asp: Request.Form("formvar")
Request.QueryString("getvar")
php: $HTTP_POST_VARS["formvar"];
$HTTP_GET_VARS["getvar"];
GET and POST 變量可以交替的自動地修改到PHP變量,這是不安全地方法。
8)Server 變量
asp: 這有許多服務器變量,可以看ASP文檔. 一個例子:
Request.ServerVariables("HTTP_HOST
php: 作為ISAPI模式, 服務器變量存儲在$HTTP_SERVER_VARS數組裡。
作為CGI, 它們存貯在環境變量裡, 用$HTTP_ENV_VARS數組或getenv( )
可以得到。一個例子:
$HTTP_SERVER_VARS["HTTP_HOST"] using ISAPI module
$HTTP_ENV_VARS["HTTP_HOST"] using CGI module
9)數據庫訪問
asp: 一般用ado技術
php: ADO可以使用adodb庫來模擬,這個庫等價與ado.
限制是,目前支持只讀性光標和前滾光標.
(註解)也可以直接調用com庫,看我的文章。
10)Buffering
asp: Response.Buffer = true
Response.Write("abc");
Response.Flush()
php: ob_start();
print "abc";
ob_end_flush();
11) Script Timeout
asp: 時間級是秒級:
Server.ScriptTimeout(240)
php: 時間級是秒級:
set_time_limit(240);
php中高效能清除HTML 標記、空白字符
在字符截取時常會因為HTML格式發生意外,ASP是,PHP也是,如果是可預見的簡單HTML格式用replace就行了,對於文章正文這一類裡面可能包含所有的HTML格式,想高效點還是用下面的的,已測試
$search = array ("'
2009年5月15日 星期五
PHP 分割字串 Function 的速度比較(substr/sscanf/preg_match)
固定長度的字串(假設是 06481a63041b578d702f159f520847f8), 要照固定格式做切割, 使用 PHP 要怎麼切會比較快?
註: 要將此字串切成 => 06 / 48 / 1a63041b578d702f159f520847f8 這三個字串.
寫簡單的程式做個測試, 來比較 substr / sscanf / preg_match 的速度.
先設 $a = '06481a63041b578d702f159f520847f8';, 再執行下面程式做測試(全部都跑 100萬次的數據):
- 使用 substr 程式執行花 4.08482551575 秒:
$x[0] = substr($a, 0, 2);
$x[1] = substr($a, 2, 2);
$x[2] = substr($a, 4, 28); - 使用 sscanf 程式執行花 5.26213645935 秒 (與 substr 差 -5.26213645935)
list($x[0], $x[1], $x[2]) = sscanf($a, '%2s%2s%28s');
註: $x = sscanf($a, '%2s%2s%28s'); // 耗費時間增加到 8秒, 會比 preg_match 更慢. - 使用 preg_match 程式執行花 7.58504867554 秒 (與 substr 差: -7.58504867554)
preg_match('/^(\w{2})(\w{2})(\w{28})$/', $a, $match);
$x[0] = $match[1];
$x[1] = $match[2];
$x[2] = $match[3];
結論, substr() 大獲全勝, 還是不要懶惰, 雖然要寫比較多行, 但是速度會快不少.
2009年5月12日 星期二
str_replace, ereg_replace,preg_replace 的異同
: 查了 php 的使用手冊, 覺得有些疑問
: str_replace 照手冊說明是 php-3.0.8 就應該停止開發了?
: 建議用 ereg_replace 來取代.. 可是看不太出來有什麼不同?
: 而 ereg_replace 中有建議用 preg_replace 來取代
:
: 但是我看不出來到底這三個函數的異同在哪?
: 而 preg_replace 似乎無法做非陣列的字串取代?
語法不對..可用
:
: 英文能力不太好, 看得很模糊, 方便的話請知道的人說明指導一下..
:
: 謝謝 ^^!
:
三種都是不同的模組..所以應該說是不一樣的功能
str_replace------String functions
ereg_replace----Regular Expression Functions (POSIX Extended)
preg_replace----Regular Expression Functions (Perl-Compatible)
所以看字面上就知道下面兩種正規表示式語法上就不同了
str_replace 4.0.5以後可以像strtr那樣轉換陣列..
ereg_replace,preg_replace都各有不同的語法
但是以preg_replace最多,可以參考手冊上的Pattern Syntax
功能性上preg_replace>ereg_replace>str_replace
但是就是因為處理功能強大所以"單一置換速度"
str_repalce>ereg_replace>preg_replace
我的經驗,可以自己試試一萬個以上的陣列轉換。
2009年5月10日 星期日
解決網址傳遞中文參數時所發生的亂碼問題
以上列來說,上列最有可能是中文的,就是「$school」這個參數,而這時我們只要改成以下程式碼就可以了。
$school = "中和高中";
$school = rawurlencode($school);
php iconv Big5 to UTF-8
我在使用iconv要把Big5轉到utf8發生了問題,iconv遇到無法轉的字後,就不轉了,所以該字以後都掉字了,把是要把oracle(big5)資料轉到mysql(utf8)。
php 由oracle(big5)讀出【黃埀儀】後,用iconv轉成utf8,回傳的字只剩下【黃?(?為不可視字元】,轉到mysql後只剩下【黃】,我也 試過mb_convert_encoding,但是轉完後顯示【黃?番】,因為中間那個字很特殊沒有辦法轉過去,遇到無法轉,要怎麼樣讓後面繼續轉下去, 例如【黃埀儀】轉成【黃?儀】,謝謝。
逐字轉解決
function big52utf8($big5str) {
$blen = strlen($big5str);
$utf8str = "";
for($i=0; $i<$blen; $i++) {
$sbit = ord(substr($big5str, $i, 1));
//echo $sbit;
//echo "
";
if ($sbit < 129) {
$utf8str.=substr($big5str,$i,1);
}elseif ($sbit > 128 && $sbit < 255) {
$new_word = iconv("BIG5", "UTF-8", substr($big5str,$i,2));
$utf8str.=($new_word=="")?"?":$new_word;
$i++;
}
}
return $utf8str;
}// end func
Php Xml處理之simplexml使用方法淺談
假如我們有一個這樣的文件,
- xml version="1.0" encoding="utf-8"?>
- <phplamp>
- <post>
- <title id="1">PHP XML處理介紹一title>
- <details>詳細內容一details>
- post>
- <post>
- <title id="2">PHP XML處理介紹二title>
- <details>詳細內容二details>
- post>
- <post>
- <title id="3">PHP XML處理介紹三title>
- <details>詳細內容三details>
- post>
- phplamp>
- /**
- * 加載Xml文件
- */
- $xml = simplexml_load_file("me.xml");
- /**
- * 如果Xml為字符串的話可以用下面這個方法,後面的使用方法一樣
- * $xml = simplexml_load_string
- */
- /**
- * 遍歷$xml對象
- */
- foreach ($xml as $key => $value) {
- // 獲取屬性
- $attr = $value->title->attributes();
- echo "Id: " . $attr['id'] . "
"; - echo "Title: " . $value->title . "
"; - echo "Details: " . $value->details . "
"; - }
- ?>