“include”在PHP中的性能代价是多少?

23

我想知道包含数百个类文件的大型(600K或更大)php文件所涉及的“成本”是什么。相比于搜索多个目录以找到匹配项的逐个自动加载文件,这真的有很大区别吗?

如果开启APC缓存,这会使成本变得微不足道吗?


澄清一下,这将是ORM的“基类”。没有简单的方法通过“函数”来区分它们,它们只是数据库模式的表示。我们在每次“构建”时都会覆盖它们,并且目前我们会扩展它们两次,以进行对象和表级别的覆盖。在任何给定的请求中,我们可能会加载10-15个。在我的初始测试中,我没有看到加载完整文件和不加载之间有明显的差异。我们启用了APC,所以也许这是其中的一部分原因? - FilmJ
为什么需要在PHP脚本中包含整个数据库模式?给定的脚本只需要知道它将与之交互的少数模式元素。我能想到的唯一例外是生成整个模式表示的脚本,但即使在那里,也可以通过查询数据库来检索模式而不必在PHP中包含特定数据来实现。这听起来像是巨大的膨胀。 - cazort
3个回答

22

基本上,包含一个大文件的成本取决于您的用例。假设您有一个包含200个类的大文件。

如果您只使用1个类,则包括大文件的成本将比为该单个类包括一个小类文件更高。

如果您使用了所有200个类,则包括大文件的成本将显著低于包括200个小文件。

截止点真正取决于系统。我想象它可能在50%左右(如果您对任何请求中使用的类少于100个时自动加载)。

使用APC可能会使折点更接近于较少的类(因此,没有APC,使用100个类可能是折点,但使用APC后可能在使用50个类时达到折点),因为它使大型单个包含变得更加便宜,但仅略微降低每个单独较小包含的开销。

确切的折点将完全取决于系统(磁盘I/O速度如何、处理器速度如何、内存大小等)。因此,唯一确定您平台上的情况的方法是进行测试。

然而,比原始性能更重要的是可维护性。由于很难同时处理多个类(IDE中的选项卡变得无用),因此使用一个大文件会降低可维护性。我个人会将所有类保留在单独的文件中,使开发人员的生活更轻松,而不是制作一个庞然大物的巨大文件。

现在,如果您的网站流量达到Facebook的级别,则值得进一步调查。但如果没有,我个人不会担心它...


4
如果您发现将所有内容放入一个大文件中可以显著提高速度,您可以为生产环境创建某种“编译”脚本,将所有单独的类转储到一个文件中。这样,您就可以享受速度提升的好处,同时仍然能够在单独的文件中维护类。 - Wade Tandy
@ircmaxwell:是的,我同意,这需要的不仅仅是“foreach($files as $f) cat $f >> onefile.php”。你需要想出一些方案,在开发/测试和生产环境之间保持包含的工作原理,以及其他一些事情。 - Wade Tandy
https://github.com/EvanDotPro/EdpSuperluminal <-- 有人正在使用Zend进行这项工作。您只需点击一个URL即可自动缓存所有类...但是,如果您已经在使用APC,我想知道是否值得这样做。 - Tom
我的直觉是,防止1个数据库查询比防止100个文件包含更重要,但如果没有测试,那只是猜测。 - Steve Clay

20
我已经对php include() 的各种成本进行了一些测试,想与大家分享,因为我看到许多程序员或CMS平台忽视了这些运行前的php成本。
函数本身的成本相当微不足道。100个文件包含(空文件)约耗时5毫秒;使用opcache时不超过1微秒。
因此,与包含100个单独文件相比,包含100个类的较大php文件的成本节省仅约为5ms。而使用OpCode缓存使该成本无关紧要。
真正的成本取决于您的文件大小以及PHP需要解析和/或编译的内容。为了更好地了解这些成本,请参见我在2010年Mac Mini Server上进行的测试结果,该服务器配备10,000 RPM驱动器,运行启用优化器的eAccelerator opcache的PHP 5.3。
1µs  for 100 EMPTY File includes, w/opcache
5ms  for 100 EMPTY File includes, no opcache

7ms   for 100 32KB File includes, w/opcache
30ms  for 100 32KB File includes, no opcache

14ms  for 100 64KB File includes, w/opcache
60ms  for 100 64KB File includes, no opcache

22ms  for 100 128KB File includes, w/opcache
100ms for 100 128KB File includes, no opcache

38ms  for 100 200KB File includes, w/opcache
170ms for 100 200KB File includes, no opcache

因此,一个600KB的php文件大约需要6毫秒,或者使用opcode缓存时大约需要1毫秒。你真正需要关注的是每个请求中包含的所有代码的大小。

尝试合并文件以节省资源绝对不是一个好主意,并且在使用op-cache时会是一个错误。我的测试几乎不考虑磁盘速度,因为我将同一个文件包含了100次。也就是说,我不觉得有必要完全涵盖磁盘I/O,因为安装op-cache实际上是基本性能的先决条件。

为了尽可能提高性能并节省RAM使用量,我们必须做相反的事情。这就是尽可能地按上下文分割文件,使用自动加载器或类工厂模式,为每个请求包括尽可能少的未使用的代码。

为此,滥用include_once() 也可能会带来负面的性能影响...

关于您的基础类。我有类似的情况,但我只包括表模式的一小部分。主要是字段类型和主键细节。出于性能原因,我故意不始终包括表的相当沉重的模式,因为它们很少使用,而且当它们被使用时,每个请求最多只使用其中几个。
每个表的平均完整列细节大约为20-50k每个模式数组。在任何给定的请求中包括10-15个这样的数组成本大约为1-3毫秒。这本身并不多。但与每个请求节省500k RAM相结合时,它变得值得。

4
终于有真实数字了,而不是理论。 - vatavale

1

APC可以为您节省很多,但如果您的源代码达到600k,那么它是否可以忽略不计就不得而知了。这大约是15000行代码?对于一个网站来说并不算太多,但对于单个文件来说相当大。

您最好使用更动态的方法,并将特定功能隔离在特定类中。然后,对于每个页面,您可以选择需要哪些代码。

特别是当您使用APC时,这种方法会更好,因为您不必从磁盘加载许多小文件时承担文件I/O的开销。我会选择实现小型指定类并将每个类放在单独的文件中。您可以使用PHP类加载机制(__autoload)自动加载正确的单元。

当您为类和单元想出一个良好的命名约定时,这将使您的开发变得更加容易。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接