什么是一些很好的PHP性能提示?

时间:2010-11-16 15:44:33

标签: php performance

我听说过PHP的一些性能提示,例如根据情况使用strtr()而不是str_replace()超过preg_replace()

至于使用某些功能而不是代码风格,您知道哪些性能提示?

编辑:我不是在谈论使用那些使代码不易读取的东西,例如!isset($foo{5})而不是strlen($foo) < 5,我正在谈论的事情就像在ereg_函数上使用preg_函数来进行正则表达式。< / p>

编辑:我之所以问这个问题,不是为了挑战何时进行优化,而是为了大致了解在一组有限的替代方案中最有效的方法。例如,检查mysql语句是否返回错误可以说是比开始时抑制错误更好的做法。

13 个答案:

答案 0 :(得分:36)

这个问题真的很模糊。如果要优化脚本,首先要检查数据库并尝试优化算法。没有太多纯粹的PHP性能提示是重要的。我们来看看:

  • 连接变量比将它们放在双引号中更快。

    $var = 'Hello ' . $world; // is faster than
    $var = "Hello $world"; // or
    $var = "Hello {$world}";
    

是的,速度更快,但第二种和第三种形式更具可读性,速度损失很低甚至无关紧要。

  • 使用循环时,如果条件使用常量,则将其放在循环之前。例如:

    for ($i = 0; $i < count($my_array); $i++)
    

这将每次评估count($ my_array)。只需在循环之前创建一个额外的变量,或者甚至在内部:

for ($i = 0, $count = count($my_array); $i < $count; $i++)
  • 最糟糕的事情肯定是循环内部的查询。要么是因为缺乏知识(试图在PHP中模拟JOIN),要么就是因为你没有考虑它(例如很多插入循环中)。

    $query = mysql_query("SELECT id FROM your_table");
    while ($row = mysql_fetch_assoc($query)) {
        $query2 = mysql_query("SELECT * FROM your_other_table WHERE id = {$row['id']}");
        // etc
    }
    

从不这样做。这是一个简单的INNER JOIN。

可能还有更多,但实际上,不值得将所有这些都写下来。编写代码,稍后进行优化。

P.S。当没有时,我开始写这个答案,链接中可能已经有一些东西了。

编辑:由于某种原因,我无法正确格式化代码。我真的不明白为什么。

答案 1 :(得分:22)

预测优化是所有恶劣的根源

这是你需要的最重要的提示。如果有一天您遇到了真正的性能问题,请查看您的应用程序,检测受损区域,然后再来这里询问:)

答案 2 :(得分:8)

66优化PHP的提示

以下是韦伯的观点:

  • 使用JSON而不是XML。
  • 也可以使用sprintf代替双引号中包含的变量,速度提高约10倍。
  • 避免PHP mail()函数头注入问题。
  • 如果方法可以是静态的,则将其声明为静态。速度提高了4倍。
  • echo比打印更快。( *与John Lim的phplens列表进行比较
  • 使用echo的多个参数代替字符串连接。
  • 设置for循环的最大值,而不是循环。
  • 取消设置变量以释放内存,尤其是大型数组。
  • 避免像__get,__ set,__ autoload
  • 这样的魔法
  • require_once()很贵
  • 在包含中使用完整路径,并且需要花费更少的时间来解析操作系统路径。
  • 如果您需要找出脚本开始执行的时间,$ _SERVER ['REQUEST_TIME']优先于time()
  • 看看你是否可以使用strncasecmp,strpbrk和stripos代替正则表达式
  • str_replace比preg_replace快,但strtr比str_replace快4倍
  • 如果函数(如字符串替换函数)接受数组和单个字符作为参数,并且参数列表不是太长,请考虑编写一些冗余替换语句,一次传递一个字符,而不是一个接受数组作为搜索和替换参数的代码行。
  • 最好使用select语句而不是multi if,else if else。
  • 使用@进行错误抑制非常慢。
  • 启用apache的mod_deflate
  • 完成后关闭数据库连接
  • $ row ['id']比$ row [id]
  • 快7倍
  • 错误消息很昂贵
  • 不要在for循环中使用函数,例如for($ x = 0; $ x&lt; count($ array); $ x)每次调用count()函数。
  • 增加方法中的局部变量是最快的。与在函数中调用局部变量几乎相同。
  • 增量全局变量比本地变量慢2倍。
  • 增加对象属性(例如$ this-&gt; prop ++)比局部变量慢3倍。
  • 增加未定义的局部变量比预先初始化的变量慢9-10倍。
  • 只是声明一个全局变量而不在函数中使用它也会减慢速度(与增加局部变量的速度大致相同)。 PHP可能会检查全局是否存在。
  • 方法调用似乎与类中定义的方法数量无关,因为我在测试类中添加了10个方法(在测试方法之前和之后),性能没有变化。
  • 派生类中的方法比基类中定义的方法运行得快。
  • 使用一个参数和一个空函数体的函数调用与执行7-8 $ localvar ++操作的时间大致相同。类似的方法调用当然是大约15 $ localvar ++ operations。
  • 用'而不是'来围绕你的字符串将使事情解释得更快,因为php在“...”内查找变量但不在'...'内。当然,只有在字符串中不需要变量时才能执行此操作。
  • 当回显字符串时,用逗号而不是点分隔它们会更快。注意:这仅适用于echo,这是一个可以将多个字符串作为参数的函数。
  • Apache脚本将比Apache的静态HTML页面至少慢2到10倍。尝试使用更多静态HTML页面和更少的脚本。
  • 除非缓存脚本,否则每次都会重新编译PHP脚本。安装PHP缓存产品通常可以通过删除编译时间将性能提高25-100%。
  • 尽可能地缓存。使用memcached - memcached是一个高性能的内存对象缓存系统,旨在通过减轻数据库负载来加速动态Web应用程序。 OP代码缓存很有用,因此不必在每个请求上编译脚本
  • 使用字符串时,您需要检查字符串是否具有一定的长度,您可以理解为使用strlen()函数。这个函数很快,因为它的操作不执行任何计算,只返回zval结构中可用的已知字符串长度(用于在PHP中存储变量的内部C结构)。但是因为strlen()是一个函数,它仍然有点慢,因为函数调用需要几个操作,如小写和&amp;哈希表查找,然后执行所述函数。在某些情况下,您可以使用isset()技巧来提高代码的速度 的实施例

    view sourceprint?1.if(strlen($ foo)&lt; 5){echo&#34; Foo太短&#34 ;; }

    <强> VS

    view sourceprint?1.if(!isset($ foo {5})){echo&#34; Foo太短&#34 ;; }

    调用isset()恰好比strlen()更快,因为与strlen()不同,isset()是一种语言结构,而不是一个函数意味着它的执行不需要函数查找和小写。这意味着在确定字符串长度的实际代码之上几乎没有任何开销。

  • 当递增或递减变量$ i ++的值恰好比++ $ i慢一点。这是PHP特有的,不适用于其他语言,所以不要修改你的C或Java代码,认为它会突然变得更快,它不会。 ++ $ i恰好在PHP中更快,因为代替用于$ i ++的4个操作码,你只需要3.后增量实际上会导致创建一个临时var然后递增。预增量直接增加原始值。这是像Zend的PHP优化器一样优化的操作码优化之一。记住这一点仍然是一个好主意,因为并非所有操作码优化器都执行此优化,并且有大量ISP和服务器在没有操作码优化器的情况下运行。
  • 并非所有内容都必须是OOP,通常是开销太大,每个方法和对象调用会消耗大量内存。
  • 不要将每个数据结构都实现为类,数组也很有用
  • 不要过多地分割方法,想一想,你会真正重用哪些代码
  • 您可以随时在需要时分割方法代码
  • 利用无数的预定义功能
  • 如果您的代码中有非常耗时的函数,请考虑将它们编写为C扩展
  • 描述您的代码。分析器会向您显示代码的哪些部分消耗了多少时间。 Xdebug调试器已包含一个分析器。分析显示了概述中的瓶颈
  • mod_gzip可作为Apache模块使用,可以动态压缩您的数据,并可以减少数据传输,最高可达80%
  • 关于优化PHP的优秀文章John Lim

正如Reihold Webber指出John Lim发表的一篇文章(发现这篇文章在没有声明源的情况下复制了),然后我进一步研究,这是一个优化PHP代码性能的优秀最佳实践教程,涵盖了几乎所有方面低级Web服务器配置,PHP配置,编码样式和性能比较。

cluesheet.com中编写的另一个更好的PHP性能的好方法是:

  • 请在双引号上使用单引号。
  • 使用切换多个if语句
  • 每次迭代都要避免使用函数测试来测试循环条件,例如。为($ I = 0; I&LT =计数($ x)的; $ I ++){...
  • 使用foreach来循环集合/数组。 PHP4项是byval,大于PHP5项是byref
  • 在创建复杂的PHP类时,请考虑使用Singleton方法。
  • 对于因TCP / IP数据包性能原因而在数据库中出现的所有值,请使用POST over GET。
  • 为了性能原因,请在正则表达式上使用ctype_alnum,ctype_alpha和ctype_digit来测试表单值类型。
  • 在basename / fileexists / open_basedir上使用生产环境中的完整文件路径,以避免必须通过文件路径搜索的文件系统的性能命中。确定后,在$ _SETTINGS数组中序列化和/或缓存路径值。 $ _SETTINGS [&#34; CWD&#34] = CWD(./);
  • 使用require / include over require_once / include_once来确保正确的操作码缓存。
  • 使用tmpfile或tempnam创建临时文件/文件名
  • 使用代理使用XMLHTTP访问外部域上的Web服务(XML或JSOM)以避免跨域错误。例如。 foo.com&LT; - &GT; XMLHTTP&LT; - &GT; bar.com
  • 请使用error_reporting(E_ALL);在调试期间。
  • 将Apache allowoverride设置为“none”以提高访问文件/目录时的Apache性能。
  • 使用快速文件服务器来提供静态内容(thttpd)。 static.mydomain.com,dynamic.mydomain.com
  • 将路径等应用程序设置序列化为关联数组,并在首次执行后缓存或序列化该数组。
  • 使用PHP输出控制缓冲来缓存重访问页面的页面缓存
  • 使用PDO准备本机db准备语句。 mysql_attr_direct_query =大于1
  • 不要使用SQL通配符选择。例如。 SELECT *
  • 使用数据库逻辑(查询,连接,视图,过程)而不是循环PHP。
  • 如果不使用PDO参数参数,请对SQL insers使用快捷语法。例如。 INSERT INTO MYTABLE(FIELD1,FIELD2)VALUES((“x”,“y”),(“p”,“q”));

参考 - gist.github.com

我访问了其他博客并比较了以上所有要点,并尝试在此处添加所有内容以优化您的PHP代码。

希望这会对你有所帮助。

答案 3 :(得分:5)

如果您正在寻找有关如何对代码进行编程以获得最佳效果的好提示,请参阅http://www.phpbench.com/。它们对编程的各个方面进行了大量比较,因此您可以使用最适合您需求的方法。通常,它取决于您是否希望节省处理能力或内存使用量。

http://talks.php.net/show/digg/0 - PHP自己就性能发表的演讲

http://code.google.com/speed/articles/optimizing-php.html - Google关于如何加快申请速度的建议

最常见的问题不是PHP,而是MySQL或http请求问题。

答案 4 :(得分:5)

这个看起来有点极端但是......

PHP非常慢。这是不可否认的。它是其中之一 那里最慢的语言。如果你真的想要获得最佳表现,我将会在这里停留并使用其他语言。

您可能无法获得最佳性能,因为计算机今天往往非常强大,并且可以选择扩展或缓存。随着新版本的发布,PHP也会变得更快,尤其是PHP 7,因此最近声明可能会为您带来免费的性能提升。版本之间的差异可能会使一些微观优化毫无意义。

完全违背关于PHP是最慢的语言的声明,你可能会发现在某些情况下它几乎击败了每种解释语言。这是因为PHP原本是一个非常简单的C包装器,许多PHP函数都包含了C函数,这使得它们非常快。这实际上往往是大多数解释语言的情况,但它在PHP中更为明显。

与此相反,一些内置函数可能会出现性能问题,因为它们试图做得太多或者没有很好地实现。我认为直到PHP 7 array_unique以一种非常奇怪且过于复杂的方式实现,它会更快地使用诸如array_flip和array_keys之类的东西。

PHP就是这样。它是最令人发指的语言之一,因为它具有一系列极端对立的矛盾属性。它是最不稳定但最容易学习的之一。 PHP是最糟糕的语言之一,其有机发展比坚持设计更加强大,但它是最高效的语言之一,作为用于Web开发的DSL。当在Apache下运行时,PHP非常难以扩展其中一种最具伸缩性的Web语言。我可以继续,但重点是在PHP方面会产生混淆。

抛弃PHP并非没有代价。 PHP中的生产力往往比webdev的其他语言要高得多,而且入门的标准非常低。

如果你想拥有两全其美的优势,那么只需使你的PHP代码尽可能简单,其目标主要是它的工作而不是快速。此后的下一步是确保保留良好的日志,以便您可以找到具有最高延迟或占用最多资源的请求。一旦你知道这一点,就可以进行有针对性的分析。您可以这样想,您的日志会告诉您要分析的文件或请求,您的分析会告诉您哪些行或代码块很慢。

不要忘记,虽然PHP通常不是缓慢或难以扩展但PHP脚本依赖的其他资源,例如数据库。

一般资源监控也很有用。例如,如果您的环境CPU使用率低于5%,为什么要做任何事情,除非延迟出现在某个地方?这也有助于为您提供有关PHP停滞位置的更多提示(瓶颈所在的位置,网络,HDD IO,内存,CPU等)。还要记住,今天的硬件确实非常便宜,并且在问题上抛出硬件可能会变得更加有效。这种监测再次允许有针对性的方法。我是一位经验丰富,经验丰富的老人,我可以告诉你,我过去曾经过早地优化了很多。这将带来良好的回报,但今天却没有。通常情况下,我可以花一个月的时间来优化某些东西,并且以相同的工时成本购买一些硬件,这可能会导致性能提高两倍而不需要付出很多努力。我不会把这个放得太远,硬件并没有解决所有问题,只是按照这样看待它,无论你多少尝试优化,硬件都有硬限制,所以如果你试图让它与劣质硬件一起工作太过分你会很快达到收益递减的境界。

一旦找到这些问题区域,您就可以尝试使用更好的PHP或缓存来优化它们。在大多数情况下,这可能就足够了。通常,您可能会发现PHP不是瓶颈,而是数据库访问等其他内容。

如果您发现无法在PHP中进行优化或使用缓存,则必须考虑其他问题。使用另一种语言是一种选择,当然这里有可能使用C然后将其作为扩展包装在PHP中。一般来说,编写C的代价很高,因此这种方法只允许您在需要的地方使用它,或者更确切地说是在您获得最大利益的地方。这称为热点优化。

除此之外还有许多其他选择,你不需要只包装C,但如果PHP不能这样做,PHP就无法做到。您还可以考虑在多个节点或进程之间进行扩展,但请记住,在某些情况下,由于没有共享,因此PHP在并行处理方面不能很好地扩展(没有多少扩展加载需要共享以获得收益)。

无论你决定什么,当它归结为它时,我们可以给出关于微优化的1000个提示。也许是最好的全能之一,我可以给你尝试尽可能多地放入尽可能少的PHP本机函数,因为这些将在C中以更快的速度运行批量操作。在涉及诸如时间复杂性之类的事物的算法设计时,您还应该遵循良好的理论概念,因为这些概念是普遍适用的。事实上,人们可以给你的大多数性能提示可能是一般的编程概念而不是PHP特有的。我还建议避免库膨胀或庞大的框架。他们承诺的越多,就越有可能在现实世界中变得太好。简单是关键,虽然库总是很好的思考,你是否包括一万行代码,以节省你写出十行中的十行,你可以把它变成一个函数并重用自己。

如果使用低于5.5的PHP版本,使用Opcache或APC将立即提高PHP解析时间的速度,并使其成为一个无关紧要的问题。 PHP 5.5应该内置它,但要确保它已启用。

什么比什么情况下更快的事情让成千上万的东西与成千上万的东西相比,所以你最好的选择是研究和了解PHP实际上是什么,它是如何工作的,以及如何测量,测试和分析性能。如果您对PHP的工作原理有充分的了解,那么当它们出现问题时,您将能够更好地解决问题。优化十行代码可以成为一个10000字的辩论。想想你的应用程序,当它有数千行代码。

在一些情况下,我确实理解先发制人和微观优化的重要性或好处(主要包括避免在性能不成比例地降低的语言中的性能怪癖)。然而实际上通常几乎不可能达到你期望的那种收益(尽管我不得不说,如果你真正关心性能,那么你可以拥有的最大影响就是完全放弃PHP,基本上这可以看作是问问如何我可以快速制作一只蜗牛吗?答案是,如果速度如此重要,请使用为此制作的东西)。即使是经验丰富且知识渊博的人也可能会遇到困难。几乎没有人第一次就做对了。因此,您真正想要花费精力的是可维护性。保持代码的一致性,整洁性和组织性。使用VCS可以轻松删除内容(不要注释掉代码或将文件重命名为.old)。确保你保持干爽,一般遵循良好做法。 TIAS,谷歌等

答案 5 :(得分:4)

通常,预先成熟的优化是一个不好的主意。当单个SQL查询需要80ms时,使代码运行速度提高0.5ms并不重要。

你应该分析代码并专注于瓶颈,然后尝试缓存(静态,APC,Memcached)之类的东西。当您拥有完美的应用程序设计并且仍需要某些模块/功能的更高性能时,微优化是最后一步。

答案 6 :(得分:1)

让我们想象你有一系列单词 像这样:$words=array('banana','cat','tuna','bicycle','kitten','caffeine');

然后你会找到一个搜索词,如下所示:$find='ca';

并且您想知道使用该术语开始的所有元素。

我们通常会这样做:

foreach($words as &$word)if(preg_match('@^'.$find.'@',$word))echo $word,'<br>';

或者最快的方式:

foreach($words as &$word)if(strpos($find,$word)==0)echo $word,'<br>';

但为什么我们不这样做:

foreach($words as &$word)if($find==($find&$word))echo $word,'<br>';

你削减了几个字节而且它更快,因为你不必浪费时间来调用函数。

答案 7 :(得分:1)

这个问题(以及答案)相当过时,但是当我搜索“PHP性能”时,它在列表中显得很高。

虽然jgmjgm提出了一些好处,但PHP的执行时间通常只是用户等待页面显示时间的一小部分,但explaining why, let alone detailing the remedies在这里花费的时间太长了。

第一步是识别花费最多时间的东西 - 对于基于Web的应用程序,您应该从浏览器开始。谷歌浏览器有一个很好的分析器,对于Firefox,有Firebug扩展。如果慢速位是PHP,那么使用xdebug等分析器进一步挖掘,但请记住,这将包含任何数据库和文件IO。

答案 8 :(得分:0)

尽可能使用单引号而不是双引号。 (甚至是变量,听起来很傻) 滥用PHP关联数组,它们是哈希表,并且对于任何类型的查找都非常快。

但是,不要过分关注低级别的表现。您在PHP中执行的任务通常非常简单。它们通常经常重复。这意味着你应该对速度的真正关注点是PHP的边缘。

关注PHP和数据库之间的速度。在出路时关注标记的大小。专注于缓存。

非常罕见的是,你会看到代码本身优化的任何一种胜利。至少在选择一个功能而不是另一个功能的规模上。显然,你想避免多余或无用的重复。但除此之外你不应该担心。

答案 9 :(得分:0)

您必须在优化之前进行测量。没有测量,你就没有目标。没有目标,你就是在浪费时间。

如果您发现您的网页需要250毫秒才能呈现,那还够快吗?如果没有,它应该多快?它不会降到零。你需要200毫秒吗?

使用XDebug(http://www.xdebug.org/)之类的工具来确定代码中的热点位置。您可能会发现您的应用程序占用了80%的时间来访问数据库。如果您的应用需要200毫秒才能从数据库中获取数据,而{.1}}调用则需要.01毫秒,那么转到str_replace或使用strtr代替echo的加速很小,无关紧要。

能够使用print代替strtr并获得明显的,可衡量的加速的梦想是一种幻想。

答案 10 :(得分:0)

很明显,但创建对象也很昂贵,所以对于ex。如果你需要一个时间戳做一个time()比做一个date_create() - &gt; getTimestamp快两倍。

for ($a=1;$a<1000000;$a++) {
  $e = time(); // In my tests about 2x faster than:
  //$e = date_create()->getTimestamp();
}

答案 11 :(得分:0)

  1. 使用本机PHP函数
  2. 使用单个行情
    使用单引号('')比使用双引号(“”)
  3. 更快
  4. 使用= = =
    使用“= = =”而不是“= =”,
  5. 只计算一次 如果该值被多次使用而不是一次又一次地计算它,那么计算并赋值给变量。

    例如,以下内容会降低性能。

    for( $i=0; i< count($arrA); $i++){
    
     echo count($arrA);
    }
    

    下面的脚本会表现得更好。

    $len = count($arrA);
    
    for( $i=0; i< $len; $i++){
    echo $len;
    

    }

  6. 二手Switch案例

  7. 使用JSON
  8. 在使用Web服务时使用JSON而不是XML,因为像json_encode()和json_decode()这样的本机php函数非常快。 7.使用isset 尽可能使用isset()而不是使用count(),strlen(),sizeof()来检查返回的值是否大于0.

    1. 连接变量比将它们放在双引号中更快。

答案 12 :(得分:0)

  1. 请将绑定变量视为数据库的statament,而不是将它们放入SQL子句中。对于Oracle RDBMS和MySQL,同样的方法也是类似的,也许是其他方法(解析,绑定,执行)。带有绑定变量的查询可以更快地为运行它们做好准备。
  2. 如果您要插入多行,则可以使用一个批量DML