【问题标题】:Optimize my performance优化我的表现
【发布时间】:2026-01-04 14:40:01
【问题描述】:

我正在使用 Zend Framework 1.11、Doctrine 2、一些 Symfony 2 组件和其他工具和库进行项目。

我正在尝试使用 Xdebug 和 Webgrind 优化性能。

我已经发现了一些瓶颈,比如解析 Ini 配置等。并缓存了它。

现在,我才意识到自动加载是我的应用程序中最昂贵的部分:

    Opl\Autoloader\ApcLoader->loadClass                    274   31.36   43.86
    Zend_Loader_PluginLoader->load                         150    4.80   12.29
    Zend_Loader_Autoloader->getClassAutoloaders            278    1.42    1.91
    Zend_Controller_Router_Route_Regex->_getMappedValues   291    1.29    1.35
    Doctrine\ORM\UnitOfWork->createEntity                   85    1.24    3.18

如您所见,我没有使用默认的 Zend_Loader_Autoloader,我使用的是 Opl,据我所知,这比它更快,我使用的是带有 APC 缓存的 classMapLoader,但是与应用程序的其他部分相比,它仍然有点慢。

我该如何优化它?

我已经加载了大约 250 个类,看起来只有 ~40 个很慢,其他显示 0,00 作为“总调用成本”,但其他在 require 调用时从 0,08 增加到 0,57。

顺便说一句,由于使用了 Opl 自动加载器,看起来在我的生产环境 APC 上只有操作码缓存“手动需要”的文件,而不是自动加载器调用的文件。

【问题讨论】:

    标签: php performance zend-framework optimization autoloader


    【解决方案1】:

    如果重构代码不是一种选择(放弃 Zend Framework、Drop Doctrine、Drop ...),我会首先优化购买更好的硬件。这将自动优化您的代码,因为代码的上下文只是被转移了(这并不是完全优化代码,因为代码不会改变)。

    如果这不是一个选项,请考虑为自己创建一个构建系统,该系统可以预处理您的代码库并创建它的非开发版本以减少加载过程。这需要分析始终需要哪些文件,然后将它们全部编译成加载器优化的格式,可以是单个文件和/或静态类加载器映射。

    但是众所周知,Zend 总是需要将大量内容加载到内存中。即使使用像 APC 这样的 PHP 缓存也可能已经为您带来了一些好处(考虑使用前面提到的构建脚本进行预编译并优化您的指标突出显示的部分)。

    如果您的应用程序结构允许,还有另一种可能性:在请求之间将整个应用程序保留在内存中。这可以通过 PHP 网络服务器来完成。完成后,代码只需要在服务器启动后加载,并且永远不需要再次加载。如果它支持多个请求,这仅适用于您自己的应用程序。一个很好的封装应用程序,特别是带有请求逻辑的应用程序可以很容易地被采用。现有的解决方案是appserver-in-php。与您已经从 APC 获得的好处相比,您会惊讶于速度的提高。

    也许这很有帮助。很难提出任何额外的、更具体的建议,因为无法看到您的代码正在运行,也无法获得详细的指标。您刚刚传递了关于幕后发生的事情的片段,因此很难更具体地告诉您。

    【讨论】:

    • 感谢您的出色回答,实际上我的问题是我从带有 ZF1.7 和 Zend_Db 的老式应用程序迁移而来,它的事务率(由 siege 给出)返回类似于 30/40/s 我所在的位置只有 10 个,但是我做了很多优化,比如查询优化,可以减少全局请求时间,但我对这样的速度有点失望。购买新硬件肯定是一种解决方案,它会是,但我也不希望它成为解决方案。查看自动加载器时,看起来 Doctrine 需要的文件比 Zend 框架本身更多。
    • 考虑您的应用程序中是否真的需要 ORM。如果您不这样做,请放弃学说,只使用 table 数据网关row 数据网关 zend 库提供。或者只是使用 PDO 中的 PHP 本机 mysql 驱动程序坚持您自己的数据库抽象。如果数据库是您的瓶颈,请将您的代码和数据库靠得更近,以缩短路径。这可能会减少 ORM 提供的一些舒适选项,但您会更快,并通过创建自己的函数来获取和推送数据到 mysql 存储来编写自己的舒适代码。
    • 我喜欢放弃各种东西的建议(即减轻负担)。我不喜欢“购买更好的硬件。这将自动优化您的代码”的建议。这就像说如果骑师太胖,就买一匹更快的马。芯片供应商的勤奋工程师做了惊人的工作,为我们提供了更快的硬件。我想知道他们是否知道程序员正在依赖它,而不是从代码中获取脂肪?
    • @MikeDunlavey:感谢您分享您对硬件扩展的看法。我认为它在某些情况下是有效的,所以我实际上提到了它,但这只是多个建议中的一个。直到今天还没有真正受到法律的约束,我们可以减少多少地球资源,所以现在,如果你仍然可以获得更多的力量,那就去吧。当这结束时,程序员需要再次改变这个烂摊子,所以它是一个完美的工作机器,可以在今天生成胖代码,然后在 10 年左右的时间里将其解散。这同样适用于硬件设计师。 ;)
    • @Mike Oh 但是 KIWI(用铁杀死它)适用于许多公司。事实上,这些公司每年都在使用它!如果它不起作用,他们肯定不会经常使用它? ;) 虽然我认为在某些情况下,如果您已经使用通常的技巧进行了优化,并且必须重写大部分代码以进行进一步优化 - 毕竟工程师只有这么多,而且总是比我们做的更多可以:)
    【解决方案2】:

    我不喜欢 hakre 的建议。首先,我会看看是否可以删除 Web 服务器。如果是这样,一个不错的选择是 nginx 或 lighttpd。与本世纪的 Apache 相比,它们的配置也容易得多。关于自动加载我真的不知道,但是如果类文件真的很大,您是否尝试安装 ram 磁盘或使用 php 压缩器?根据我的经验,PHP 压缩器可以显着加快执行时间(即解析时间)。

    【讨论】:

      【解决方案3】:

      我正在尝试使用 Xdebug 和 Webgrind 优化性能

      好的,既然您正处于迫切需要更好性能的位置,您可能会接受一种不太受欢迎但明显有效的方法。

      它适用于任何语言,只要有可以暂停的调试器,例如 Xdebug。

      这里描述为in a nutshellHere's one demonstration of its effectiveness. 我可以给你更多链接。

      你可能会觉得这有点智力上的痛苦。如

      1. 您发现“瓶颈”是与例程相关的时间。最有价值的加速机会通常不会以这种方式表现出来。它们是您在看到它们时可以轻松描述的活动,但它们是分散的。它们不会将大量时间集中在任何特定的例程或代码行上,因此分析器看不到它们。

      2. 最大的加速机会可能根本不容易解决。他们可能需要重新考虑计划的组织方式。如果您找到可以轻松解决的问题,那就太好了。继续做吧。如果它不是那么容易修复,但仍然可以节省大量时间,如果您需要节省时间,那么您必须这样做,无论喜欢与否。

      祝你好运。

      【讨论】:

        【解决方案4】:

        我没有太多经验,但曾经遇到过这样的问题。我检查了我的包含路径并按照最大使用库路径的顺序对它们进行了排序。我得到了将近 30% 的提升。我想你已经知道了,但已经发布了任何方式....... :)

        【讨论】: