PHP 从固定格式字符串里解析数据最快的方式

为了提升 PHP M3u8 的解析速度,我在上一篇博客里评选出了 PHP 世界里判断是否由某字符串开头最快的冠军,这一次又要举行另外一个比赛了:从某个固定格式的字符串里解析出想要的数据最快的函数。

还是以 M3u8 格式举例子。如果我想从字符串 #EXT-X-VERSION:3 取出 3 这个版本号,可能大家最好想到的是利用正则来实现:

不过,既然 PHP 也属于 C Family,也比较容易想到另外一个函数也可以实现同样的需求:

从语法上来看,两者都还比较简单,sscanf 略胜一筹,但我们最关心的速度又如何呢?做个实验比一比:

结果怎样大家可以在自己电脑上实验一番,在我的电脑上 sscanf 胜,但差距也不是很大,在一个数量级内。

另外我不得不补充一点,sscanf 用法还是很灵活的,比如在解析 #EXT-X-BYTERANGE:1000@500 时,因为 @ 以及它后面的参数是可以省略的,如果用 preg_match 来处理:

而使用 sscanf 的话:

当没有 @500 时,$offset 自动就是 null,所以一行代码就可以搞定,就冲这点 sscanf 也加分不少。不过我们还是再来测试一下这种方式的速度对比:

结果依然是 sscanf 获胜。

对于解析 #EXT-X-VERSION:3 这种格式比较简单的,方法还有很多,比如利用 explode, substr, strstr 等函数,我打算再加赛一场,看看是否能跟 sscanf 一争高下。在看结果之前,不妨自己猜猜看谁是冠军:

得益于上一届的冠军 strpos 出色的性能,strpos + substr 组合以大优势获得了冠军!substr + strrchr 组合获得亚军,substr + strstr 组合获得季军。不得不说 substr 还是很牛逼的,前三名它都有出镜。

2017-11-17 补充:今天又试验了 substr + strlen 的组合,以不大的优势超越了曾经的冠军获得了第一名!以上代码已经更新。

当然这些方法只能用在特殊情况,正常解析带格式的字符串还是得用回 preg_matchsscanf。事实上,sscanf 也是可以使用正则的,但要注意不是所有正则符号都能用,跟一般的正则还是有所区别:

sscanf 加正则的格式的方式与 preg_match 以及 sscanf 自身比一比:

再猜猜看结果是什么??

公布结果:

带正则 sscanf 稍快于 preg_match,稍慢于不带正则的 sscanf

经过这次的比赛,再次告诉我们一个真理:正则能别用就别用啊。

wx pay

CC BY-NC-ND 4.0 PHP 从固定格式字符串里解析数据最快的方式 by Chrisyue's Blog is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.

发表评论

电子邮件地址不会被公开。

thirty − = twenty three