找出PHP代码减速的位置(性能问题)

时间:2008-09-11 02:47:50

标签: php mysql performance profiling

这是我在SO的第一个问题。

我有一个我公司的内部申请,我最近要求维护。这些应用程序是用PHP构建的,它的编码相当好(OO,DB Abstraction,Smarty),没有WTF-ish。

问题是应用程序非常慢

如何找出减慢应用程序速度的方法?我已经优化了代码,只进行了很少的数据库查询,所以我知道这是需要一段时间才能执行的PHP代码。我需要一些可以帮助我的工具,并且需要设计一个检查我的代码的策略。

我可以自己做检查/策略工作,但我需要更多的PHP工具来弄清楚我的应用程序在哪里。

思想?

12 个答案:

答案 0 :(得分:39)

我最近在类似的情况下使用了XDebug profiling。它输出一个完整的配置文件报告,可以使用许多常见的配置文件应用程序读取(虽然不能给你一个列表,我只使用了slackware附带的那个)。

答案 1 :(得分:9)

正如Juan所说,xDebug很棒。如果您使用的是Windows,WinCacheGrind会让您查看报告。

答案 2 :(得分:6)

观看Rasmus Lerdorf(PHP的创建者)的演讲。他介绍了一些测试PHP速度和寻找内容的好例子,以及一些可以减慢速度的内部组件。 XDebug是他使用的一种工具。他还非常清楚地了解您在使用框架时遇到的性能成本。

视频: http://www.archive.org/details/simple_is_hard

幻灯片(因为在视频中很难看到): http://talks.php.net/show/drupal08/1

答案 3 :(得分:3)

有许多变量会影响应用程序的性能。我建议您不要立即假设PHP是问题。

首先,您如何为PHP服务?您是否尝试过Apache或IIS本身的基本优化?服务器是否忙于处理其他类型的请求?你有没有利用PHP code accelerator?测试服务器是否是您的瓶颈的一种方法是尝试在另一台服务器上运行该应用程序。

其次,整个应用程序的性能是否缓慢,还是只影响某些页面?这可以为您提供从何处开始分析性能的指示。如果整个应用程序运行缓慢,则问题更可能发生在底层服务器/平台或全局SQL查询中,该查询是每个请求的一部分(例如,用户身份验证)。

第三,您提到最小化SQL查询的数量,但是优化现有查询呢?如果您使用的是MySQL,您是否正在利用每个存储系统的各种优势?您是否对最重要的查询运行EXPLAIN以确保它们已正确编入索引?这对于访问大表的查询至关重要;数据集越大,您就越会注意到索引不良的影响。幸运的是,有许多文章such as this one解释了如何使用EXPLAIN。

第四,常见的错误是假设您的数据库服务器将自动使用系统可用的所有资源。您应该检查以确保已为数据库应用程序显式分配了足够的资源。例如,在MySQL中,您需要为密钥缓冲区,临时表大小,线程并发,innodb缓冲池大小等内容添加自定义设置(在my.cnf文件中)。

如果您已经仔细检查了上述所有内容并且仍然无法找到瓶颈,那么像Xdebug这样的代码分析器肯定会有所帮助。就个人而言,我更喜欢Zend Studio分析器,但它可能不是最好的选择,除非你已经利用了Zend Platform堆栈的其余部分。但是,根据我的经验,PHP本身很少是导致性能下降的根本原因。通常,代码分析器可以帮助您更准确地确定哪些数据库查询应该受到责备。

答案 4 :(得分:2)

phpED(http://www.nusphere.com/products/phped.htm)还提供了出色的调试和分析功能,以及在PHP代码中添加监视,断点等功能。集成的分析器直接在IDE中提供每个函数调用和类方法的时间细分。浏览器插件还可以与Firefox或IE快速集成(即使用浏览器访问慢速URL,然后单击按钮进行配置或调试)。

在指出应用程序速度慢的地方以便集中大部分编码工作时非常有用;它避免浪费时间优化已经很快的代码。尝试过Zend和Eclipse之后,我现在已经以phpED的易用性出售了。

请记住,对网络服务器进行调试时,Xdebug和phpED(使用DBG)都需要安装额外的PHP模块。 phpED也提供了(我未尝试过)本地调试选项。

答案 5 :(得分:2)

Xdebug简介绝对是最佳选择。另一个提示 - WincacheGrind很好,但最近没有更新。 http://code.google.com/p/webgrind/ - 在浏览器中可能是一种简单快捷的替代方案。

但是,很可能,无论如何它仍然是数据库。检查相关索引 - 并且它有足够的内存来尽可能多地缓存工作数据。

答案 6 :(得分:2)

此外,您可以使用APD(高级PHP调试器)。

很容易让它发挥作用。

$ php apd-test.php

$ pprofp -l pprof.SOME_PID

Trace for /Users/martin/develop/php/apd-test/apd-test.php
Total Elapsed Time = 0.12
Total System Time  = 0.01
Total User Time    = 0.07


         Real         User        System             secs/    cumm
%Time (excl/cumm)  (excl/cumm)  (excl/cumm) Calls    call    s/call  Memory Usage Name
--------------------------------------------------------------------------------------
71.3 0.06 0.06  0.05 0.05  0.01 0.01  10000  0.0000   0.0000            0 in_array
27.3 0.02 0.09  0.02 0.07  0.00 0.01  10000  0.0000   0.0000            0 my_test_function
 1.5 0.03 0.03  0.00 0.00  0.00 0.00      1  0.0000   0.0000            0 apd_set_pprof_trace
 0.0 0.00 0.12  0.00 0.07  0.00 0.01      1  0.0000   0.0000            0 main

有一个很好的教程,如何编译APD并使用它进行分析:http://martinsikora.com/compiling-apd-for-php-54

答案 7 :(得分:1)

如果你是一个庞大的代码库,请尝试apc,如果你还没有。

http://pecl.php.net/package/APC

答案 8 :(得分:1)

你也可以尝试在php中使用register_tick_function函数。它告诉php在你的代码中调用某个函数。然后,您可以跟踪当前正在运行的功能以及呼叫之间的时间量。然后你可以看到花费最多的时间。 http://www.php.net/register_tick_function

答案 9 :(得分:0)

我们使用Zend Development Environment(windows)。我们昨天解决了内存使用率峰值,在运行Process Explorer时逐步调试调试器,以便在执行每一行时观察内存/ CPU /磁盘活动。

Process Explorer:http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx

ZDE包含一个基本的性能分析器,可以显示页面请求期间每个函数调用所花费的时间。

答案 10 :(得分:0)

我使用PEAR Benchmarklog4php的组合。

在我要配置的脚本顶部,我创建了一个包裹Benchmark_Timer对象的对象。在整个代码中,我添加了$object->setMarker("name");次调用,特别是在可疑代码周围。

包装器类有一个destroy方法,它接收日志信息并将其写入log4php。我通常将此发送到syslog(许多服务器,聚合到一个服务器上的一个日志文件)。

在调试中,我可以查看日志文件,看看我需要改进的地方。稍后在生产中,我可以解析日志文件并进行性能分析。

它不是xdebug,但它始终打开并且让我能够比较代码的任何两次执行。

答案 11 :(得分:0)

如果服务器性能下降是应用程序处理速度缓慢的原因,您还可以查看HA Proxy或任何其他负载平衡解决方案。服务器。

相关问题