提醒:本文最后更新于 2837 天前,文中所描述的信息可能已发生改变,请仔细核实。
在前期文章《全新WordPress评论管理系统》,我提到了为何写这个插件,最主要的原因,还是因为后台评论编辑管理页面慢。想想显示20条评论要近6秒时间,这谁能忍。所以只能自己做一个轮子。
但作为一个爱折腾,愿解决实事的人,逃避不是我的风格(这句纯属胜利者装逼)。
我新建了Wordpress,使用原始主题,将现有主题的所有文章、评论、附件、类别移到这个新Wordpress。
发现后台评论编辑管理页面速度特别快,即便设置显示100条也0.11秒左右显示。
启用Memcached外部对象缓存,发现速度依然如旧,飞快。
这说明两种可能,我想到的两种:第一种主题问题,第二种WP升级遗留问题。
所以在新Wordpress启用了新主题,测试后台评论编辑管理页面,速度慢下来了,要5秒多。
因为主题模块化了,并且把功能分类后,归类到文件。
所以很好排除,二分法禁用这些模块,发现是Wordpress钩子模块出问题,其中只有几个是关于评论的。最终定位是一个“清除评论里的其他计数”的函数,hook对象是get_comments_number
。
add_filter('get_comments_number', 'comment_count', 0); function comment_count( $count ) { global $id; $comments_by_id = get_comments('status=approve&post_id=' . $id); $comments_by_type = separate_comments($comments_by_id); return count($comments_by_type['comment']); }
因为get_comments_number
本身获取的是该文章的所有评论计数,而一篇文章的评论计数,不单只是评论,还有Trackbacks、Pingbacks,而评论还有已通过、待审核、垃圾评论等。
所以这个函数主要就是为了修复这一问题,因为我们一般只为了获取已通过审核的评论,其他都不要。
好,那么来看看这个函数,初看没什么大问题。但是不知从哪个版本开始,那个id参数回值是空。也就是说不知什么时候Wordpress不主动全局定义这个参数了。我看了下,貌似只在文章主循环会传递,其他留空。
这可就捅破了天了,因为id是空,那么post_id就是空了。
get_comments
就会获取所有通过评论的数量,然后返回计数给get_comments_number
,而后台评论编辑管理页面以get_comments_number
得到的数量,请求这些评论的所有缓存,如果缓存不存在就创建。
这本来是好事,但因为一个微小的错误,加上我们后台是显示20条评论。也就是相当于要20次缓存的判断、建立等动作,虽然Wordpress会合并id后然后再去请求数据库,但对id却不去重,也就是数据库会返回20*通过评论总数量的请求,然后php再一一进行缓存判断,不存在的建立,这花费了大量时间(这是我猜测的,因为那一瞬间MySQL发送了大量数据,而php单进程也占用100%)。而显示越多评论,各应用压力就更大。
知道原因就好办了,直接查到Wordpress的get_comments_number
原始函数,发现其过滤器为:
return apply_filters( 'get_comments_number', $count, $post_id );
也就是说他可以传递两个参数,其中就有我们需要的重要参数,$post_id
。
于是修改下“清除评论里的其他计数”函数,改成如下:
add_filter('get_comments_number', 'comment_count', 0, 2); function comment_count( $count, $post_id ) { $comments_by_id = get_comments('status=approve&post_id=' . $post_id); $comments_by_type = separate_comments($comments_by_id); return count($comments_by_type['comment']); }
如此,便解决了该问题。
目前设置显示100条评论,只要1/3秒,这速度能接受。用了这个函数慢0.2秒,能接受的。
Had 3 queries, using 14.30MB memory, page to load in 0.349 seconds
这个函数算是历史遗留函数,基本上旧版的大多数主题都会用到,比较实用。
我的主题一直继承这个函数,所以就出现这一问题。各位老哥们,还用这个函数,注意要脱坑啊。
原始作者已经不知是谁,但当时可能没考虑太多,又能用,写成这样已经不错了。
出现这种问题,主要还是升级遗留问题,没去更新这个函数(当然,也不会想到这个问题)。
不过好在发现并解决了。
而且刚刚的“清除评论里的其他计数”函数还不是最原始的模样,我留存中这个函数最原始的模样如下(爱收藏的命,这是3.3版本时的记录):
add_filter('get_comments_number', 'comment_count', 0); function comment_count( $count ) { global $id; $comments = get_approved_comments($id); $comment_count = 0; foreach($comments as $comment){ if($comment->comment_type == ""){ $comment_count++; } } return $comment_count; }
在Wordpress跟踪了下get_comments_number
的原始函数,发现从2.9版本开始,开始传递两个参数,count和post_id,而在2.8.6还只传递一个参数,number。
也就是说可以看出当时那个写“清除评论里的其他计数”函数的作者,并不会利用和使用get_comments_number
原始函数的第二个参数。
id什么时候没全局就不知道了,这个没追踪,太多依赖函数了。不管了。
转载请注明转自:kn007的个人博客的《解决后台评论编辑管理页面慢的问题》
不如把精力放在有意义的事情上
@大发:
一如既往的支持折腾精神。
@郑永: 哈,是的~
我怎么没有发现有速度上的问题?
@土木坛子: 默认主题应该没什么问题。
之前主要是因为后台 /wp-admin/edit-comments.php 慢,现在找到原因就不慢。
前台的话一直不受影响,没什么问题。
还是新的评论系统快啊。
另外,自己搭建评论系统,就经常出事情。后台查了,发现自己把Ghost的主题文件当成配置文件,塞进Supervisord的配置文件夹里了,评论系统直接宕机……
@云间守望: 哈哈哈
我一直玩不转WP,就撤了
@文栋说自媒体: 不折腾也差不多
哪里找得到插件开发教程嘛
@helsing.lee: 还真不知道,我插件是先按照传统php写好,然后再移植到wordpress对接起来
@helsing.lee: 我估计也就是我才这么奇葩的作法。
太技术了,真心看不懂
@秦大叔: 谦虚了
不错,过来膜拜一下!