启动性能和过滤规则列表加载性能 - fang5566/uBlock GitHub Wiki

解析原始过滤规则列表是一项 CPU 和内存资源密集型任务。兼容 Adblock Plus 的过滤规则语法较为复杂,因此解析时要耗费大量 CPU 资源 。uBlock 还支持解析 hosts 文件,这无疑又提高了解析复杂度。虽然 uBlock 解析速度令人满意,但不代表它就不必尝试继续提高这方面的性能。

所以 0.8.9.0 版本就着重提高解析性能。方法很简单,创建并缓存一份经过编译的过滤规则列表,这样下次加载到内存的时候就不必重新执行解析操作:

图 1

经过编译的过滤规则列表内容基本确定不变,所以解析起来并不复杂,从而提高了启动性能(启动时间越小越好):

图 2

就算规则列表需要重新加载,其性能也有所提升:

图 3

编译后的过滤规则列表是由一系列 原子 规则组成,也就是功能上无法继续分解的规则。兼容 ABP 的过滤规则语法允许使用合成的规则,即一条规则可以代替多条规则。比如 EasyList 里面的一条原始规则:

/advertisers.$image,script,subdocument

在 uBlock 看来,这实际上是三条不同的规则:

/advertisers.$image
/advertisers.$script
/advertisers.$subdocument

它还很容易变得更复杂(以添加域名选项为例):

/advertisers.$image,script,subdocument,domain=example.com|whatever.org

它会在内部被翻译为:

/advertisers.$image,domain=example.com
/advertisers.$script,domain=example.com
/advertisers.$subdocument,domain=example.com
/advertisers.$image,domain=whatever.org
/advertisers.$script,domain=whatever.org
/advertisers.$subdocument,domain=whatever.org

这些都是原子规则,无法再分解为更细的规则。

编译过滤规则列表不只是将其 原子化,还包括尽可能多地预先计算,使其更接近于内存中的过滤规则形式,这样可以减少编译列表翻译为内存数据所耗费的工作量。

大概情况就是这样。

使用经过编译的过滤规则列表还会带来其他好处,比如可以精确统计出不同规则的条数,完整 检查重复的规则。在 0.8.9.0 之前的版本当中,uBlock 就尝试检查重复规则,但效果不完美, 因为它用的是规则的原始形式来判断该规则是否已被处理。

这表示 uBlock 无法判断出下面两条规则实际上是重复的,即使它们本质上干的活是一样的:

/advertisers.$image,script
/advertisers.$script,image

在 0.8.9.0 里,由于所有规则都会被分解为原子规则形式,uBlock 就可以 100% 检查出哪些规则在功能上是重复的。

考虑到 uBlock 统计的是原子规则的条数,所以预计后一个版本显示的规则条数会多于前一个版本。例如,使用默认规则列表时,0.8.9.0 会显示超过 58,000 条网络规则,而前一个版本只会显示大约 55,000 条。