The DoYouHaoBaby PHP Framework中文开发文档手册
Copyright(c) DoYouHaoBaby.NET All Rights Reserved.
[ PHP的代码优化 ]

0、用单引号代替双引号来包含字符串,这样做会更快一些。因为 PHP会在双引号包围的字符串中搜寻变量,单引号 则不会。

  1. // 单引号字符串,提倡   
  2. echo 'Hello DoYouHaoBaby!';   
  3.   
  4. // 双引号字符串,不提倡   
  5. echo "Hello DoYouHaoBaby!";   
  6.   
  7. // 当然如果是字符串中有变量的话,就用双引号(字符串中的变 量最好用{}包起来 )   
  8. // 最好不要用连接符号"."连接字符串和变量   
  9. $sWho = 'DoYouHaoBaby';   
  10. echo "Hello  {$sWho}!";  

注意:只有echo能这么做,它是 一种可以把多个字符串当作参数的“函数” ( 译注:PHP手册中说echo是语言结构,不是真正的函数,故把 函数加上了双引号 )。   

1、如果能将类的方法定义成static ,就尽量定义成static,它的速度会提 升将近4倍。

  1. // 这里不高效,因为test可以作为静态方法   
  2. class demo{   
  3.   
  4.    static protected $_sVar;   
  5.       
  6.    public function test( ){   
  7.          
  8.        return self::$_sVar;   
  9.    }   
  10. }   
  11.   
  12. // 这里改为静态方法   
  13. class demo{   
  14.   
  15.    static protected $_sVar;   
  16.       
  17.    public static function test( ){   
  18.          
  19.        return self::$_sVar;   
  20.    }   
  21. }  

2、$arrRow[’id’] 的速度是$arrRow[id] 的7倍。( 如果不加''还会引起PHP警告,所以要养成良好的编程 习惯。 )

  1. $arrRow = array ( 'id'=>'Hello world' );   
  2.   
  3. // 高效   
  4. $arrRow[’id’]   
  5.   
  6. // 不高效,且容易引起PHP 警告   
  7. $arrRow[ id ]  

3、echo 比 print 快,并且使用echo的多重参数(译注:指用逗号而不是句点)代替字符串连接,比如echo $sStr1,$sStr2。

  1. $sStr  = 'Hello';   
  2. $sStr2 = 'DoYouHaoBaby';   
  3.   
  4. // 高效   
  5. echo $sStr,$sStr2;   
  6.   
  7. // 还行   
  8. echo $sStr.$sStr2;   
  9.   
  10. // 不高效   
  11. print( $sStr.$sStr2 );  

PHP中echo和print的区别:

PHP 和 HTML 最简单的交互是通过 print 和 echo 语句来实现的,在实际使用中, print 和 echo 两者的功能几 乎是完全一样。可以这么说 ,凡是有一个可以使用的地方,另一个也可以使用。

但是,两者之间也还是一个非常重要的区别:在 echo 函数中,可以同时输出多个字符串 ,而在 print 函数中则 只可以同时输出一个字符串。同时,echo函数并不需要圆括号,所以echo函数更像是语句而不像是函数。

echo 和 print 都不是函数,而是语言结构,所以圆括号都不是必需的。他们的区别在于:

(1) echo可以输出多个字符串,像下面这样:

  1. echo 'a','b','c';   

如果你非要加上圆括号,注意写成echo ('a','b','c');是错误的,应该写成:  

  1. echo ('a'),('b'), ('c');   

它没有像函数的行为,所以不能用于函数的上下文.

(2) print只能输出一个字符串,它可以表现得像一个函数,比如你可以如下使用:

  1. $sRet = print 'Hello World';   

所以它能用在更复杂的表达式中。

(3) echo的效率相对比较快 如下代码

  1. // echo 可以用逗号分隔字符串变量来显示 print $sA.$sB.'<br />';   
  2. // 而print不能使用逗号,只能用点号分隔, print $sA,$sB.'<br />';   
  3. // 使用逗号时报错。   
  4. $sA='hello ';   
  5. $sB='php world!';   
  6. echo $sA,$sB.'<br />';  

4、在执行for 循环之前确定最大循环数,不要每循环 一次都计算最大值,最好运用foreach 代替。

  1. // 在执行for循环之前确定最大循环数,不要每循环一次都 计算最大值。也就是说,   
  2. $nCount = count ( $arrResult );   
  3. for( $nI=0;$i<=$nCount;$nI++ ){    
  4.   
  5. }    
  6.   
  7. // 切勿下面这个   
  8. // 这样每循环一次都要执行count()函数,如果$count值足够大, 那就扯了。   
  9. for( $nI=0;$nI<=count ( $arrResult );$nI++ ){   
  10.   
  11. }    

5、注销那些不用的变量尤其是大数组,以便释放内存。

  1. // 我们假设$sValue是一个很大的字符串,比如内容管理系 统的文章正文   
  2. // 我们用完了,应该立刻删除它   
  3. echo $sValue;   
  4. unset( $sValue );  

6、尽量避免使用 __get, __set, __autoload。   

7、require_once()代价昂贵。   

8、include文件时尽量使用绝对路径,因为它避免了 PHP去include_path里查找文件的速度,解析操作系统路径所需的时间会更少。    

9、如果你想知道脚本开始执行(译注:即服务器端收到 客户端请求)的时刻,使用$_SERVER[‘REQUEST_TIME’]要好于time() 。

  1. // 脚本开始执行   
  2. $nStartTime = $_SERVER [‘REQUEST_TIME’];   
  3.   
  4. // time()不够准确   
  5. $nStartTime = time ();  

10、函数代替正则表达式完成相同功能。   

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

12、如果一个字符串替换函数,可接受数组或字符作为参数,并且参数长度不太长,那么可以考虑额外写一段替换 代码,使得每次传递参 数是一个字符,而不是只写一行代码接受数组作为查询和替换的参数。   

13、使用选择分支语句(译注:即switch case 好于使 用多个if,else if语 句。

  1. $nType = 1;   
  2.   
  3. // 高效   
  4. switch( $nType ){   
  5.   
  6.    case 1:   
  7.       echo 'First';   
  8.       break;   
  9.    case 2:    
  10.       echo 'Two';   
  11.       break;   
  12.    default:   
  13.      echo 'Three';   
  14.      break;   
  15. }   
  16.   
  17. // 不推荐   
  18. if( $nType ==1 ){   
  19.       
  20.    echo 'First';   
  21. }   
  22.   
  23. else if{   
  24.      
  25.    echo 'Two';   
  26. }   
  27.   
  28. else{   
  29.      
  30.    echo 'Three';   
  31. }  

14、用@屏蔽错误消息的做法非常低效,极其低效。    

15、打开apache的mod_deflate模块,可以提高网页的 浏览速度。

Apache加速静态html元素另一法_mod_deflate :

1、编译时出错

  1. /usr/local/apache2.2.0/bin/apxs -i -a - c mod_deflate.c  

提示出错:

  1. Warning!   dlname not found in /usr/local/apache2.2.0/modules/mod_deflate.la.   
  2. Assuming installing a .so rather than a libtool archive.   
  3. chmod 755 /usr/local/apache2.2.0/modules/mod_deflate.so  

后来使用这种方式解决:

  1. gcc -shared -o mod_deflate.so mod_deflate.o   
  2. cp mod_deflate.so /usr/local/apache2.2.0/modules   
  3. /usr/local/apache2.2.0/bin/apxs -i -a - c mod_deflate.c    
  4.     
  5. <ifmodule mod_deflate.c>   
  6. DeflateCompressionLevel 9   
  7. AddOutputFilterByType DEFLATE text/html text/plain text/xml application/x-httpd -php   
  8. AddOutputFilter DEFLATE css js   
  9. DeflateFilterNote Input instream   
  10. DeflateFilterNote Output outstream   
  11. DeflateFilterNote Ratio ratio   
  12.   
  13. LogFormat '"% r" %{outstream}n/%{instream}n (% {ratio}n%%)' deflate   
  14. CustomLog logs/deflate_log deflate    
  15. </ifmodule>  

大功告成!

Linux下:

  1. "GET / HTTP/1.1" 204/387 (52%)   
  2. "GET /phpMyAdmin/ HTTP/1.1" 2474/8045 (30%)   
  3. "GET /phpMyAdmin/print.css HTTP/1.1" -/- (-%)   
  4. "GET /phpMyAdmin/phpmyadmin.css.php?lang=zh-utf- 8&convcharset=iso-8859- 1&collation_connection=utf8_unicode_ci&token=90427a95bd0b2420245d29674998be14&js_frame=right&nocache=35910319 72 HTTP/1.1" 4329/20539 (21%)   
  5. "GET /phpMyAdmin/themes/original/img/b_info.png HTTP/1.1" -/- (-%)   
  6. "GET /phpMyAdmin/themes/original/img/b_help.png HTTP/1.1" -/ - (-%)   
  7. "GET /phpMyAdmin/themes/original/img/logo_right.png HTTP/1.1" -/-  (-%)   
  8. "GET /phpMyAdmin/themes/original/img/s_notice.png HTTP/1.1"  -/-  (-%)   
  9. "GET /procedure/ HTTP/1.1" 196/342 (57%)   
  10. "GET /drupal/ HTTP/1.1" 2578/8861 (29%)   
  11. "GET /drupal/modules/system/defaults.css HTTP/1.1" 397/737 (53%)   
  12. "GET /drupal/modules/system/system.css HTTP/1.1" 1985/6932 (28%)   
  13. "GET /drupal/misc/jquery.js HTTP/1.1" 9903/19340 (51%)   
  14. "GET /drupal/modules/user/user.css HTTP/1.1" 367/858  (42%)   
  15. "GET /drupal/modules/node/node.css HTTP/1.1" 330/678 (48%)   
  16. "GET /drupal/sites/all/modules/fckeditor/fckeditor.css HTTP/1.1" 114/293  (38%)   
  17. "GET /drupal/sites/all/modules/tagadelic/tagadelic.css HTTP/1.1" 216/601  (35%)   
  18. "GET /drupal/sites/all/modules/cck/content.css HTTP/1.1" 178/368  (48%)   
  19. "GET /drupal/sites/all/modules/thickbox/thickbox.css HTTP/1.1" 948/3587& nbsp;(26%)   
  20. "GET /drupal/themes/garland/style.css HTTP/1.1" 4056/16778 (24%)   
  21. "GET /drupal/misc/drupal.js HTTP/1.1" 2145/5664 (37%)   
  22. "GET /drupal/sites/all/modules/thickbox/thickbox.js HTTP/1.1" 3318/10579  (31%)   
  23. "GET /drupal/themes/garland/logo.png HTTP/1.1" -/-  (-%)   
  24. "GET /drupal/themes/garland/fix- ie.css HTTP/1.1" 713/1412 (50%)   
  25. "GET /drupal/themes/garland/print.css HTTP/1.1" 533/1256 (42%)   
  26. "GET /drupal/themes/garland/images/body.png HTTP/1.1" -/-  (-%)   
  27. "GET /drupal/themes/garland/images/menu- collapsed.gif HTTP/1.1" -/- (-%)   
  28. "GET /drupal/themes/garland/images/menu- leaf.gif HTTP/1.1"  -/- (-%)   
  29. "GET /drupal/themes/garland/images/bg- content.png HTTP/1.1" -/- (-%)   
  30. "GET /drupal/themes/garland/images/bg-content- right.png HTTP/1.1" -/- (-%)   
  31. "GET /drupal/themes/garland/images/bg-content- left.png HTTP/1.1" -/- (-%)   
  32. "GET /drupal/themes/garland/images/bg- navigation.png HTTP/1.1" -/- (-%)   
  33. "GET /drupal/themes/garland/images/bg-navigation-item- hover.png HTTP/1.1" -/- (-%)   
  34. "GET /drupal/themes/garland/images/bg-navigation- item.png HTTP/1.1" -/- (-%)   
  35. "GET /drupal/themes/garland/images/bg- tab.png HTTP/1.1" -/- (-%)  

Windows下:

  1. "GET /kydepot/ HTTP/1.1" 816/1830 (44%)   
  2. "GET /kydepot/App/View/rec/css/index.css HTTP/1.1" 795/2274 (34%)   
  3. "POST /kydepot/index.php? controller=Default&action=certify HTTP/1.1" 199/280 (71%)   
  4. "GET /kydepot/App/View/rec/css/input.css HTTP/1.1" 814/1847 (44%)   
  5. "GET /kydepot/index.php? controller=cargo&&action=list HTTP/1.1" 1621/12555 (12%)   
  6. "GET /kydepot/App/View/rec/css/input.css HTTP/1.1" 814/1847 (44%)   
  7. "GET /kydepot/index.php? controller=Cargo&action=List&page=1 HTTP/1.1" 1601/12854 (12%)   
  8. "GET /kydepot/App/View/rec/css/input.css HTTP/1.1" 814/1847 (44%)   
  9. "GET /kydepot/index.php? controller=cargo&&action=show HTTP/1.1" 1750/17412 (10%)   
  10. "GET /kydepot/App/View/rec/css/cargo.css HTTP/1.1" 708/1734 (40%)   
  11. "GET /kydepot/index.php? controller=Cargo&action=Detail&recid=0.4DA-PBA(TA) HTTP/1.1" 1294/4837 (26%)   
  12. "GET /kydepot/App/View/rec/css/cgdetail.css HTTP/1.1" 730/1944  (37%)   

2. 安装mod_deflate

  1. /usr/local/apache224/bin/apxs  -i -c - a mod_deflate.c  

apxs命令参数说明:

-i 此选项表示需要执行安装操作,以安装一个或多个动态共享对象到服务器的modules目录中。

-a 此选项自动增加一个LoadModule行到httpd.conf文件中,以激活此模块,或者,如果此行已经存在,则启用之。

-A 与 -a 选项类似,但是它增加的LoadModule命令有一个井号前缀(#),即此模块已经准备就绪但尚未启用。

-c 此选项表示需要执行编译操作。它首先会编译C源程序(.c)files为对应的目标代码文件(.o),然后连接这些目标 代码和files中其余的目标 代码文件(.o和.a),以生成动态共享对象dsofile 。

如果没有指定 -o 选项,则此输出文件名由files中的第一个文件名推测得到,也就是默认 为mod_name.so 。

如果是新安装apache,直接加上 --enable-headers --enable-deflate 即可

3. 配置mod_deflate

  1. vi /usr/local/apache224/conf/httpd.conf   
  2. LoadModule deflate_module     modules/mod_deflate.so  

此LoadModule需要放在libphp5.so之后
  1. <IfModule mod_deflate.c>   
  2.  DeflateCompressionLevel 7   
  3.  AddOutputFilterByType DEFLATE text/html text/plain text/xml application/x -httpd-php   
  4.  AddOutputFilter DEFLATE css js   
  5. </IfModule>  

压缩等级的调整有两种说法,不过懒得研究了,默认等级是6,890k的文件压缩出来的数据和最高的9级只 差1k,而且9级需要更多的CPU时间, 用默认的6级就可以了。   

16、数据库连接当使用完毕时应关掉,不要用长连接。

  1. // 比如mysql   
  2. mysql_close( $hLinkHandle );  

17、错误消息代价昂贵。   

18、在方法中递增局部变量,速度是最快的。几乎与在函数中调用局部变量的速度相当。   

19、递增一个全局变量要比递增一个局部变量慢2倍。( 尽量不要使用全局变量,不好管理,速度慢! )   

20、递增一个对象属性(如:$this->prop++)要比递增一个局部变量慢3倍。(计算时,不要直接直接操 作属性)

  1. class demo{   
  2.   
  3.    public $_nValue = 1;   
  4.   
  5.    // 不高效   
  6.    function demo( ){   
  7.          
  8.        for( $nI=0;$nI<10;$nI++ ){   
  9.   
  10.            $this- >_nValue ++;   
  11.        }   
  12.    }   
  13.       
  14.    // 高效   
  15.    function demo2( ){   
  16.   
  17.        $nValue = $this->_nValue;   
  18.          
  19.        for( $nI=0;$nI<10;$nI++ ){   
  20.   
  21.            $nValue ++;   
  22.        }   
  23.   
  24.        $this- >_nValue = $nValue;   
  25.    }   
  26.   
  27. }  

21、递增一个未预定义的局部变量要比递增一个预定义的局部变量慢9至10倍。
  1. // 不高效   
  2. for( $nI=0;$nI<10;$nI++ ){   
  3.       
  4.    $nValue++;   
  5. }   
  6.   
  7. // 高效   
  8. // 初始化值   
  9. $nValue = 0;   
  10. for( $nI=0;$nI<10;$nI++ ){   
  11.       
  12.    $nValue++;   
  13. }  

22、仅定义一个局部变量而没在函数中调用它,同样会减慢速度(其程度相当于递增一个局部变量)。 PHP 大概会检查看是否存在全局变量 。   

23、方法调用看来与类中定义的方法的数量无关,因为我(在测试方法之前和之后都)添加了10个方法,但 性能上没有变化。   

24、派生类中的方法运行起来要快于在基类中定义的同样的方法。   

25、调用带有一个参数的空函数,其花费的时间相当于执行7至8次的局部变量递增操作。类似的方法调用 所花费的时间接近于15次的局部 变量递增操作。   

26、Apache解析一个PHP脚本的时间要比解析一个静态HTML页面 慢2至10倍。尽量多用静态HTML页面,少用脚本。   

27、除非脚本可以缓存,否则每次调用时都会重新编译一次。引入一套 PHP缓存机制通常可以提升25%至100%的性能,以免除编译开销。

28、尽量做缓存,可使用memcached。memcached是一款高性能的内存对象缓存系统,可用来加速动态Web应用程序,减轻数据库 负载。对运算码 (OP code)的缓存很有用,使得脚本不必为每个请求做重新编译。   

29、当操作字符串并需要检验其长度是否满足某种要求时,你想当然地会使用strlen()函数。

此函数执行起来相当快,因为它不做任何计 算,只返回在 zval 结构( C的内置数据结构,用于存储PHP变量 )中存储的已知字符串长度。但是,由于strlen()是函数,多多少少会有些慢 ,因为函数调用会经过诸多步骤,如字母小写化 (译注:指函数名小写化,PHP不区分函数名大小写)、哈希查找,会跟随被调用的函数一起 执行 。在某些情况下,你可以使用isset() 技巧加速执行你的代码。   

(举例如下)    

  1. if (strlen($sFoo) < 5) { echo  “sFoo is too short”$$ }  
(与下面的技巧做比较)
  1. if (!isset($sFoo{5}))  { echo “sFoo is too short”$$ }   

调用isset()恰巧比strlen()快,因为与后者不同的是,isset()作为一种语言结构,意味着它的执行不需 要函数查找和字母小写化。也就 是说,实际上在检验字符串长度的顶层代码中你没有花太多开销。   

34、当执行变量$nI 的递增或递减时,$nI++ 会比++$nI慢一些。这种差异是PHP 特有的,并不适用于其他语言,所以请不要修 改你的C或 Java代码并指望它们能立即变快,没用的。

++$nI更快是因为它只需要3条指令(opcodes),$nI++ 则需要4条指令。后置递增实际上会产生一个 临时变 量,这个临时变量随后被递增。而前置递增直接在原值上递增。这是最优化处理的一种,正如Zend的PHP 优化器所作的那样。牢记这个 优化处 理不失为一个好主意,因为并不是所有的指令优化器都会做同样的优化处理,并且存在大量没有装配指令优化器的互联网服务提 供商 (ISPs) 和服务器。   

35、并不是必面向对象 (OOP) ,面向对象往 往开销很大,每个方法和对象调用都会消耗很多内存。   

36、并非要用类实现所有的数据结构,数组也很有用。   

37、不要把方法细分得过多,仔细想想你真正打算重用的是哪些代码?   

38、当你需要时,你总能把代码分解成方法。   

39、尽量采用大量的PHP 内置函数。   

40、如果在代码中存在大量耗时的函数,你可以考虑用C扩展 的方式实现它们。   

41、评估检验(profile)你的代码。检验器会 告诉你,代码的哪些部分消耗了多少时间。 Xdebug调试器包含了检验程序,评估 检验总体上 可以显示出代码的瓶颈。   

42、mod_zip可作为Apache模块,用来即时压 缩你的数据,并可让数据传输量降低 80%。   

43、在可以用file_get_contents替代file、 fopen、feof、fgets等系列方法的情况下,尽量用 file_get_contents,因为他的效率高得多 !但是要注意file_get_contents在打开一个URL 文件时候的PHP版本问题;   

44、尽量的少进行文件操作,虽然PHP的文件操作效率也不低的;   

45、优化Select SQL语句,在可能的情况下尽 量少的进行Insert、Update操作;   

46、尽可能的使用PHP内部函数(但是我却为了找个PHP里面不存在的函数,浪费了本可以写出一个自定义函 数的时间,经验问题啊!);  

47、循环内部不要声明变量,尤其是大变量:对象(这好像不只是PHP里面要注意的问题吧?);   

48、多维数组尽量不要循环嵌套赋值;   

49、在可以用PHP内部字符串操作函数的情况下,不要用正则表达式;   

50、foreach效率更高,尽量用foreach代替 while和for循环;   

51、用单引号替代双引号引用字符串;   

52、“用$nI+=1代替$nI=$nI+1。符合c/c++的习惯,效率还高”;   

53、对global变量,应该用完就unset()掉;