重构Wordpress以提高内存性能


63

我仔细查看了Wordpress的内存消耗。在我的网站上,似乎为每个页面命中分配了20MB的RAM,只是为了为所有插件的运行准备一个舒适的环境。因此,我对它进行了绘制:

没有一个地方可以优化,没有一个坏家伙会消耗大部分的内存。消费分布在许多许多php模块中。

我们如何才能使Wordpress仅在内存中初始化其环境一次,然后为每次命中多次重复使用它?我不想让缓慢的PHP在每次用户单击时都占用20 MB的空间-即使在具有大量内存的服务器上,也要花费数秒钟才能完成所有工作。基本上,您将需要可重用的只读内存块。

还有...为什么20MB?谁能提供对此的见解?

编辑:这是在我的开发计算机上运行的Wordpress上的WinCacheGrind输出(比共享主机快得多)。如您所见,仅花费一秒钟的时间就可以生成主页的HTML。通过共享主机降低速度,您会遇到麻烦。我选择了大部分时间使用的方法。您将如何进行优化?

编辑:这是此出色的functions.php分析工具的查询统计信息。

负载:12个查询-532ms-19.1MB-43次缓存命中/ 53
查询:15个查询-563ms-19.0MB-72个高速缓存命中次数/ 86
显示:21个查询-705毫秒-19.2MB-234个高速缓存匹配数/ 257

编辑:您是否想看到某些保证会吓到您的东西?将这些行插入index.php的末尾:


echo "<pre>\n";
print_r(get_defined_vars());
echo "</pre>\n";

我试图计算当前帖子的正文存储在内存中的次数。我计算了20个实例。然后我意识到PHP具有引用计数,因此副本的数量减少到只有三个:两个似乎在WP_Query中,一个在对象缓存中。我正在进一步调查。

这就是为什么我认为WordPress需要针对内存问题进行重构的原因。您再也不能将其内存消耗归咎于其功能的复杂性。它只是做错了很多事情。

编辑:经过一天的努力,这是我的发现:

1)88%的内存来自require或include或include_once调用类型:

2)php文件包含的内容大部分发生在服务请求的第一部分(并不奇怪),这也是消耗所有内存的地方:

3)绘制请求期间正在执行的所有功能非常有趣。共有12000多个电话。我将它们抖动以使其更加可见(“ Level”轴基本上是堆栈的深度):

4)我能想到的唯一方法是最大程度地减少包含的.php文件的数量。如果我将每个文件的功能分开,则可以看到许多文件最多被命中一次或两次。我们需要一种在不需要它们时如何跳过它们的方法。例如,我的远程数据库备份插件已加载并注册,根本就从未使用过。这是上面的图,按文件名分割:

我提供的赏金值得我所有声誉:)的重构,这将使我的博客内存占用减少30%或更多。

编辑:我安装了WP 3.1,这是与旧版本的比较。

蓝色是WP 3.1,红色是3.0.4。新的WP更快,​​但也占用更多内存。

这是包含文件的列表。

这让我意识到“ All In One SEO包”消耗了多少内存-一种途径是仅使用插件功能的一小部分来获取我想要的东西。另外,我自己的插件似乎还不错。

我想尝试对有条件加载,例如comment.php(我不允许在博客上发表评论)和其他几个条件。我删除了所有不推荐使用的代码。我整理了kses.php以仅按需加载其全局表。我简化了l10n(我不进行本地化),使它的函数立即返回字符串,而无需查找。我距离我随意设置的30%的目标还差得很远。

编辑:我下载并启用了APC的默认设置(操作码缓存为32MB)。比较如下:

您会看到代码加载速度大大加快,并且代码占用的内存也更少(可能是因为我们只处理操作码,而不是原始源代码)。但是,内存消耗仍然很高。


您可以将cachegrind文件本身上传到某个地方吗?请注意,我不记得其中是否包含任何值得保密的内容,如果有,那就不要。
拉斯特


1
嗯,我同意您的结论-真的没有任何事情跳出来,要求解决。我已经将新的配置文件转储到了本地测试堆栈(3.1,MS,二十,主题单元测试数据)中,并得到了1.5s(大多数差异似乎是由于自定义菜单-事情太糟糕了)。因此,我想没有什么可以解决=缓存研究。
拉斯特

@Rarst非常感谢您的帮助。我确实认为需要解决一些问题,但这需要将Wordpress的体系结构更改为完全不同的哲学,这是太多的工作。
Roman Zenka

Answers:


25

不值得的麻烦。WordPress不会因为它而占用很多内存。它消耗大量内存,因为它在后台运行了许多功能。

使用静态缓存插件缓存结果(生成的页面)并为其提供服务更加容易和有效。这样,大多数访问者甚至都不会点击WP本身。


2
我已经在使用缓存,但是仍然有一些页面实际上是动态的(例如购物车)。当星星没有正确分配时,用户可以等待20秒-即在GoDaddy上允许,但即使没有,我认为至少也要3秒左右。我根本无法提供人们习惯于Google的那种真正敏捷的体验。
Roman Zenka

8
@Roman Zenka,如果您有特定的性能需求,那么您最好是寻找特定的解决方案,而不是希望WordPress本身会变得神奇而快速,并节省资源。我建议看的第一件事是操作码缓存和片段静态缓存...但是在此之前,您需要先对其进行基准测试,不仅要确定内存的去向,还要确定花在哪里。WordPress本身就是环境,而不是瓶颈。瓶颈在于您的工作方式。
罗斯特2011年

@Rarst我实际上已经对CPU使用情况进行了基准测试,并且我不能将手指放在任何引起问题的特定位置。与记忆类似-它似乎遍布各处。但是,我的基准测试可能不是以最佳方式完成的-我使用了XDebug分析器和Cachegrind-例如,由于数据库调用而很难区分延迟。我将为更好的分析技术提供帮助。
Roman Zenka

添加了@Rarst Profiling屏幕截图。
Roman Zenka

4
也可能是GoDaddy的服务器运行缓慢。他们以没有最好的硬件而闻名,他们会“ 宁愿为电视广告付费而不是升级服务器
Zack

23

这就是为什么我认为WordPress非常需要重写的原因。您再也不能将其内存消耗归咎于其功能的复杂性。它只是在做错事。

天真的结论。阅读您不应该做的事情,第一部分

不过,感谢您的内存使用情况图。

后来的编辑: Autommatic发布了一个名为prefork的库,该库似乎可以满足您的要求:将WordPress代码仅在RAM中加载一次。


是的,这很幼稚。也许我应该说“重构”而不是“重写”,但这听起来要好得多。发布更新。
Roman Zenka

2
好的,如果您有具体的建议(尤其是补丁),欢迎将其发布在trac上:core.trac.wordpress.org
scribu 2011年

我正在处理它。我正在尝试在内存中绘制对象图,因此我可以看到使用了多少对象。有没有一种工具可以进行内存转储并将其绘制出来?
Roman Zenka

5
@scribu-+1链接到Joel的帖子!
MikeSchinkel 2011年

1
好吧,请记住,可以将WP_Object_Cache替换为memcached实现等
。– scribu 2011年

17

从WordPress 3.2开始,最低要求是PHP 5.2。我认为,随着我们的努力,核心的某些部分可以开始进行重组,并使用具有自动加载功能的类。这将使我们避免加载某些代码块,除非实际需要它们。例如,如果页面视图中没有嵌入或画廊,则我们可以避免加载很多媒体代码。

但是,即使他们决定走这条路,我也希望这是一个缓慢的发展(就像已经发生的许多其他幕后变革一样)。这将需要在许多文件和代码的位置进行改组,这可能会破坏某些插件的向后兼容。

问题的一部分(如果真的可以这样称呼)是,如果没有这种条件加载,核心框架将无法提前知道生成内容视图所需的功能。因此,许多功能必须加载以防万一


@Dougal Campbell我开始悬赏这个问题,以看看我们是否可以破解至少一个这样的WordPress实例,其性能足以使现在至少30%的内存消耗改进,相对轻松。它可能会激发一些未来的发展。
Roman Zenka

条件加载虽然有可能减少内存消耗,但是在涉及操作码缓存时会损害速度。我们倾向于速度。
scribu

有关自动加载的更多想法:stackoverflow.com/questions/4788452/…–
scribu

@scribu当您说“有条件加载”时,您是在谈论自动加载,还是实际上是根据条件加载代码?它对速度有多大伤害?
Roman Zenka

1
谢谢!如我所说,我不知道WP核心是否会采用这种方式(所需的重构可能太极端了)。但是您为分析此问题所付出的努力以及所产生的图表给我留下了深刻的印象。保持良好的工作!
Dougal Campbell,

16

我们如何才能使Wordpress仅在内存中初始化其环境一次,然后为每次命中多次重复使用它?

这称为操作码缓存。

http://en.wikipedia.org/wiki/PHP_accelerator


1
我将尝试APC,看看会发生什么。当我最初问这个问题时,我的意思不仅仅是操作码缓存-我的意思是重用WordPress构建的整个环境-代码+数据。Memcached可以帮助您更快地获取数据,但是您仍将克隆服务器内存中的数据。现在看来,操作码缓存将潜在地解决所有内存消耗的约90%。
Roman Zenka

如果您有足够的资源来进行一些实验,则也可以尝试设置FastCGI环境。我对mod_php与在FastCGI下运行之间的一些比较非常感兴趣。
Dougal Campbell

5

您可能不会设法减少ram的使用量。但是,如果您使用mod_php,则可能要mod_fcgid改用。

尽管mod_php稍慢一些,但即使不需要,它也会加载php,例如提供图片,静态文件甚至是缓存。如果您有很多要求,那么这很繁琐。

使用fcgid将减少很多。

同样,使用静态缓存(如w3total缓存)将完全避免调用php 这确实是一个很大的优势:内存使用更少,数据库连接更少。


4

哈。现在我工作的一个Web应用程序,我完全打算用数据和使用超出了我的共享托管帐户可以处理超载,所以我决定-而这本来是超级容易建立WP -尝试从工作BackPress为一个框架,并仅构建我特定用例所需的内容。

因此,我已经能够将核心环境从WP中的数百个PHP文件减少到实际需要的二十个左右,同时仍然能够利用所有的db,HTTP,用户管理,格式和cron我在WordPress中喜欢的功能。

问题在于它需要大量工作,而且我永远不会相信我的hackjob可以用于我个人以外的任何用途。如果要使用完整的WP环境,请按原样使用。它之所以如此出色,是因为数以百计的开发人员在几年内对其进行了微调。就像这里的每个人都说过的那样,您将找到一个更好的托管计划并研究缓存技术,这比黑客入侵内核可能会走得更远。


1
我同意WP已经微调了很长时间。但是我认为使用特定的插件组合来进行糟糕的托管工作并不适合微调。我很好奇我能推多远。即使更改没有进入内核,但如果您认为必须的话,最好有书面记录的方式入侵内核。
Roman Zenka

3

是的,WordPress首先加载所有内容,然后执行我们要求的操作。我记得在某个地方可以在RAM中创建虚拟池,并在其中放置文件。我本来打算将整个WordPress存储在内存中(<10MB),然后我们可以节省很多I / O,仅此一项就可以提高速度。但是我从来没有机会尝试过它,而且我并不真正精通这种东西。但是看起来值得一试。


而且我同意Rarst使用静态缓存插件,以便完全不进行任何处理。但这也可以用于良好的动态。:)
Ashfame 2011年

我喜欢这个主意。我不确定这个问题有多少是由于I / O延迟引起的,有多少是由于PHP缓慢地咀嚼数据引起的。您知道如何辨别吗?
Roman Zenka

对不起,这只是我的主意。可能对性能没有太大影响,因为通常从硬盘作为块读取数据,因此可能已经获取了许多其他数据。我不太确定。
Ashfame'3

3

一些基本建议:

  1. w3总缓存插件,用于缓存..
  2. 安装并启用内存缓存,并从w3总缓存设置中启用(操作码缓存也是一个不错的选择,但与w3总缓存插件配合不佳)
  3. 最小化直接在主题文件中链接的查询。
  4. 禁用所有多余的未使用插件并删除。
  5. 优化数据库。

我正在运行一个知名的wordpress网站,每天都有大量流量。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.