一般来说,普通编辑者不应该过度关注访问性能,认真编写内容即可。作为开发者,因为涉及到编码,则需要对性能加以关注,以免影响整个站点的访问速度。

影响性能的因素

要想理解如何提升页面访问速度,首先要确定影响性能的因素。

  • 数据库查询次数。
  • 缓存命中率
  • 同步等待时间。

想要确定某一个页面具体的影响因素,可以使用F12打开控制台(ctrl+F搜索“newpp”),查看页面HTML源代码。在正文的底部,你可以找到如图所示的一段注释:

截图显示了某个页面生成所花费的开销

每一项注释都有他特定的含义:

  • CacheTime 页面缓存的保存时间。
  • CacheExpiry 页面缓存的过期时间。
  • CPUtimeUsage CPU花费的时间。
  • RealTimeUsage 实际花费的时间。
  • Preprocessor visited node count、Preprocessor generated node count、Post‐expand include size:与模板数量和大小有关。
  • Template argument size:与模板参数大小有关。
  • Highest expansion depth: 与模板嵌套深度有关。
  • Expensive parser function count:与函数解析器对数据库的压力有关。
  • Transclusion expansion time report (%,ms,calls,template):实际展开模板开销的时间。

常见问题

  • CacheTime总是当前时间。这意味着每次页面都要重新解析。请检查页面中是否使用了动态内容(Dynamic Content )。有些函数和扩展会禁止页面缓存,以保证自身总是展示最新数据。但是这样会增加整个服务器的负载,并且也影响当前页面的响应时间。另外一种可能是更新缓存(Purge)功能被滥用。每次Purge都会刷新页面的解析器缓存。第三种可能是该页面所依赖的某个模板不断的再被修改。我们建议底层的模板不要经常变动,否则每次修改所有引用过该模板的页面都要被刷新。这造成缓存命中率骤降。开发者在设计时,应避免使用底层模板存储需要经常更新的数据。页面的缓存时间一般为一周之内。超期的页面将会自然更新。


  • RealTimeUsage远远高于CPUTimeUsage。这意味着页面生成时花费了大量的时间在等待上。最可能的是在等待网络请求和IO请求。比如页面使用了过多的图片,CPU必须停下来询问图片服务器每张图片是否存在。如果页面通过Extension:ExternalData等功能请求了站外API,则CPU也必须停下等待站外API返回。有时站外的请求返回非常慢,达到了秒级,远远超过CPU处理器的时间数量级。
  • 使用了过多的模板,导致关于模板的限制超限。这常常出现在非常复杂的页面上,比如群星文明维基都出现过类似的情况。通常来讲开发者喜欢将不同的功能模块化,然后一层一层的瀑布式调用。这在编程中是非常合理的做法,但是对于模板这样做,却会让整个维基力不从心。原因是维基在模板展开上的开销要远远大于函数在程序中调用的开销。还是那句话,他们的消耗不是一个数量级的。就像是火箭速度对比人类速度。解决的方法也非常简单,一种是尽量将模板提前展开(可以使用{{subst:}}),使用较为平面化的模板架构。还有一种方法是多利用模块解决问题。
    参见:帮助:模块


  • 过多的数据库查询,导致expensive parser function count超限。很多函数解析式需要对数据库进行查询。每一次数据库查询可以近似的看做一次文件系统IO,IO和内存的处理速度同样是数量级的差距。少量的数据库查询是不可避免的,毕竟这就是数据库的用途。但是如果一个页面需要进行数百次查询才能打开,那就有点不合适了。开发者应尽量减少“expensive parser function”的使用,尤其是使用Semantic MediaWiki的开发者,应注意减少不必要的#ask。


同步转异步

通过编写JavaScript代码,可以将很多处理交给客户端来做,减少服务器的压力,提高响应速度。理论上,所有与内容呈现无关的功能(互动、帮助、提示等),都建议交由Javascript来实现。


在使用JavaScript调用静态API时,可以尽量使用http://cdn.huijiwiki.com/站点前缀/api.php而不是http://站点前缀.huiji.wiki/api.php。前者可以通过CDN实现加速。