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

问题描述 投票:19回答:13

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

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

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

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

php performance
13个回答
36
投票

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

  • 连接变量比将它们放在双引号标记字符串中更快。 qazxsw poi

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

  • 使用循环时,如果条件使用常量,则将其放在循环之前。例如 : $var = 'Hello ' . $world; // is faster than $var = "Hello $world"; // or $var = "Hello {$world}";

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

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

永远不要这样做。这是一个简单的INNER JOIN。

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

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

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


0
投票

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

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

使用XDebug(explaining why, let alone detailing the remedies)之类的工具来确定代码中的热点位置。您可能会发现您的应用程序占用了80%的时间来访问数据库。如果您的应用程序需要200ms才能从数据库中获取数据,而在http://www.xdebug.org/调用中需要.01ms,那么前往str_replace或使用strtr而不是echo的加速比如此之小以至于无关紧要。

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


0
投票

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

str_replace

0
投票
  1. 使用本机PHP函数
  2. 使用单引号 使用单引号('')比使用双引号(“”)更快
  3. 使用= = = 使用“= = =”而不是“= =”,
  4. 仅计算一次计算并将该值分配给变量,如果该值被多次使用而不是一次又一次地计算它的使用位置。 例如,以下内容会降低性能。 for ($a=1;$a<1000000;$a++) { $e = time(); // In my tests about 2x faster than: //$e = date_create()->getTimestamp(); } 下面的脚本会表现得更好。 for( $i=0; i< count($arrA); $i++){ echo count($arrA); } }
  5. 二手Switch案例
  6. 使用JSON

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

  1. 连接变量比将它们放在双引号标记字符串中更快。

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

22
投票

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

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


8
投票

66优化PHP的技巧

以下是韦伯的观点:

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

在cluesheet.com中编写的另一个更好的PHP性能实践是:

  • 在双引号上使用单引号。
  • 对许多if语句使用切换
  • 请避免在每次迭代时使用函数测试来测试循环条件,例如。为($ I = 0; I <=计数值($ 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 [ “CWD”] = CWD(./);
  • 使用require / include over require_once / include_once来确保正确的操作码缓存。
  • 使用tmpfile或tempnam创建临时文件/文件名
  • 使用代理使用XMLHTTP访问外部域上的Web服务(XML或JSOM)以避免跨域错误。例如。 foo.com < - > XMLHTTP < - > 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通配符选择。例如。选择 *
  • 在循环PHP上使用数据库逻辑(查询,连接,视图,过程)。
  • 如果不使用PDO参数参数,请使用SQL插入的快捷语法。例如。插入到MYTABLE(FIELD1,FIELD2)值((“x”,“y”),(“p”,“q”));

Ref - $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 }

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

希望这对你有所帮助。


5
投票

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

http://www.phpbench.com/ - PHP自己在性能方面的演讲

http://talks.php.net/show/digg/0 - Google关于如何加快申请速度的建议

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


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特有的。我还建议避免库膨胀或庞大的框架。他们承诺的越多,就越有可能在现实世界中变得太好。简单是关键,虽然图书馆总是很好的思考,你是否包括一万行代码,以节省你写出100行中的十行,你可以把它变成一个函数并重用自己。

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

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

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


4
投票

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

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


1
投票

让我们想象你有一系列的单词。 像这样:http://code.google.com/speed/articles/optimizing-php.html

然后你有一个搜索词可以找到,像这样:$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>';

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


1
投票

这个问题(以及答案)相当过时,但当我搜索“PHP性能”时,它在列表中出现了很高的位置。

虽然jgmjgm提出了一些好处,但PHP的执行时间通常只是用户等待页面出现的时间的一小部分,但foreach($words as &$word)if($find==($find&$word))echo $word,'<br>'; 在这里需要花费太长时间。

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


0
投票

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

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.