【问题标题】:Optimizing PHP require_once's for low disk i/o?为低磁盘 i/o 优化 PHP require_once?
【发布时间】:2011-02-03 01:23:23
【问题描述】:

第一季度) 我正在设计一个 CMS(-谁不是!)但优先考虑缓存。从字面上看,一切都被缓存了。数据库行、数据库 ID 查询、配置数据、已处理数据、编译模板。目前它有两层缓存。

第一个是操作码缓存或内存缓存,例如 apc、eaccelerator、xcache 或 memcached。如果在那里找不到条目,​​则在二级慢速缓存中搜索它,即 php 包含。

操作码缓存实际上是否比对包含 var_export 数据数组的 php 文件执行 require_once 更快?我的测试没有定论,因为我的开发箱(XAMPP 的 5.3)在安装上述任何程序时不断抛出错误。

第二季度) CMS 有许多按需自动加载的辅助类,而不是加载所有文件。大多数情况下,每个都在它之前有一个要求,因此不需要进行自动加载,但这不是问题。因为一个页面脚本可以包含多达 50/60 个帮助文件,所以我有一种感觉,如果站点处于压力之下,它会因为所有的 i/o 而崩溃。暂时忽略有输出缓存可以消除对我将要建议的内容的需要,并且操作码缓存也会使这个问题变得没有意义。我试图做的是将脚本执行所需的所有帮助文件加入一个文件中。这是可以实现的并且效果很好,但是它的副作用是显着增加了内存使用量,即使在技术上使用的是相同的代码。

您对此有何想法和看法?

【问题讨论】:

标签: php optimization hard-drive opcode require-once


【解决方案1】:

使用像 APC 这样的编译器缓存应该会有所帮助,因为它会在您的帮助文件转换为操作码后缓存它们。这意味着这些文件不仅会被缓存,而且已经在操作码中,因此每次需要它们时都不需要对其进行解析和编译。

【讨论】:

  • 谢谢,但我意识到这一点在问题中有所说明。我只是问,因为“如果”使用 cms 的人没有操作码缓存。我的很多客户主机不允许它们,因为它们没有正式支持它们(+ 它们也会导致您必须注意的分段错误)
【解决方案2】:

看起来您只是不知道要缓存什么(以及为什么)。

您无法比较“操作码缓存”和“require_once”。操作码缓存将缓存所需的代码以及其他代码。

【讨论】:

    【解决方案3】:

    首先,请记住,如果访问足够频繁,您的操作系统会将文件缓存在内存中。

    另外,不要使用require_once。它比require 慢得多。如果您不使用自动装载机,则应该使用。没有理由在现代 php 应用程序中手动包含文件(极少数例外)。

    50-60 个帮助文件太疯狂了。没有办法把这些结合起来吗?你不能把它们都放在一个相关的帮助类中,比如OutputHelperCacheHelper?这样你只需要包含这个类,同样,你应该照顾你的自动加载器。在我看来,您正在做一些事情,例如为每个文件放置一个函数。

    操作码缓存大大降低了内存使用和执行速度,但我不确定它对require 语句有什么影响。

    【讨论】:

    • 不,这些文件都是辅助类而不是函数。麻烦的是,如果我使用 require,那么如果多次包含同一个文件,您将收到类重新声明错误。我已经按照另一个线程中的建议将所有要求都切换到了 include_once,这看起来确实好一些。关于手动包含它们,它们通常不是手动包含的,很多是自动加载的,但是如果自动加载的类正在扩展或实现,那么那里有需要语句来保存自动加载。
    • @buggedcom:我敢打赌,使用include_once 比在扩展一个类并且它必须加载其父类时使自动加载器工作更困难一些更昂贵。框架非常复杂且庞大,但它们都没有手动包含。
    • @ryeguy:自动装载机的设置方式可以做到这一点。我认为这样做实际上对性能更好?
    • @buggedcom:不确定我是否明白你在说什么。如果我理解正确,您手动包含孩子的父类?例如,您有class Widget extends AbstractWidget,您会在Widget.php 文件中使用include_once 'AbstractWidget.php',对吗?我的意思是,是的,您无需在此处查找 Widget.php 就可以节省自动加载程序,但使用 (require|include)_once 很慢,因为 PHP 必须进行内部检查以查看该文件之前是否已包含。
    • 是的,你基本上已经明白我在做什么了。我的理解是使用自动加载器功能本身很慢,因此只需要一次。所以也许一个更好的解决方案是扮演我自己的加载函数,与自动加载一起可以查看请求的文件是否已经加载?我认为需要进行一些基准测试。
    【解决方案4】:

    我同意黑麦。 require_once 比 require 或 include 慢,因为它必须记录每个包含并检查它。如果你只做一个 require/include (你应该为类),那么你不需要 require_once 或 include_once。

    自动加载非常适合优化。因为您只会在需要时加载类。因此,如果您的应用程序有 500 个类,但只需要 15 个类即可运行某个页面/脚本。然后只有那 15 个被加载。哪个不错。

    如果您在任何大型框架中达到顶峰。您会注意到他们已经迁移到使用自动加载器。他们习惯在最后一刻使用 require_once,就像 Zend Framework Version 1 中的这个示例一样。

    require_once 'Zend/Db/Exception.php';
    throw new Zend_Db_Exception('Adapter name must be specified in a string');
    

    Zend Framework 版本 2 将改为使用自动加载器。我相信这是最快的,也是最容易编写代码的。

    【讨论】:

    • 天啊,你发布的链接是什么。看来这家伙根本不知道自己在做什么。每个实例运行 *_once 一千次绝对没有意义。
    • 这就是重点。您无法通过循环运行 1000 次来比较 require_once。因为在现实生活中,一切都只被称为一次。一次,你不明白吗?现实生活中没有速度差异。
    • 啊,我明白你现在在说什么了。谢谢你的解释。
    猜你喜欢
    • 2019-11-12
    • 2017-03-23
    • 2019-12-07
    • 2014-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多