mb_*系列函数真是慢啊,这种原生函数有什么好的替代品吗?

2015-08-26 19:42:19 +08:00
 Tianpu
翻了一圈资料,为了保持最大兼容性,好像又是不可替代的

自己维护一个 alphabet ,考虑到多语言,实在是太麻烦了

有没有人在这方面有过其它的尝试呢?

比如用正则替代掉?
3619 次点击
所在节点    PHP
19 条回复
jhdxr
2015-08-26 21:12:48 +08:00
很难想象正则会比 mb_系列函数快。。。另外我很好奇你具体的业务是干什么,居然瓶颈出在这函数上了?
xzem
2015-08-26 21:29:34 +08:00
正则应该会更慢些
Tianpu
2015-08-26 21:35:00 +08:00
@jhdxr 文本处理呀

虚拟机上测试
mb_stristr
mb_strtolower
mb_strtoupper
mb_convert_case
这几个都是 0.05ms 左右
对比不带 mb_的只是 0.002ms

mb_split 好一些,是 0.01ms

我预感用正则重写至少前面几个可以达到 0.01ms

正则的坏处是 mb_系列函数毕竟有它的优势,比如同意字符处理,因此重写可能有坑
Tianpu
2015-08-26 21:36:33 +08:00
@xzem 我待会先简单测试下看看, strtoupper 和 stristr
jfcherng
2015-08-26 22:23:44 +08:00
同問具體到底如何使用了這些 mb_* 函式
Tianpu
2015-08-26 23:35:57 +08:00
@xzem
@jhdxr
@jfcherng

字符串样本是 0123456789abcdefghijklmnopqrstuvwxyzÁáÀàÂâÄäÃãĄąÆæÇçÉéÈèÊêËëĘęÍíÎîÌìÏïĮįÑñÓóÒòÔôÖöÕõŒœŞşẞßÚúÙùÛûÜüŲųŸÿ0123456789abcdefghijklmnopqrstuvwxyzÁáÀàÂâÄäÃãĄąÆæÇçÉéÈèÊêËëĘęÍíÎîÌìÏïĮįÑñÓóÒòÔôÖöÕõŒœŞşẞßÚúÙùÛûÜüŲųŸÿ

随机 1000 个短文本测试 stristr ,字符串ß的大小写没有处理,其它兼容性应该不存在了

pcre 大致是只需要 5%的运行时间

pcre 内部应该也有个 unicode 的大小写字母表,匹配没有问题,转换大小写好像没什么办法

除了 mb_convert_case 外,其它 mb_*函数都应该容易改写
vibbow
2015-08-26 23:38:37 +08:00
C:\Users\vibbo\Desktop>php test.php
-----compatibility test-----
samples count: 1000
test finished

-----runtime test-----
mb_stristr () x1000
load in 0.04488ms

pcre_stristr () x1000
load in 0.01255ms

time save 72.04%
C:\Users\vibbo\Desktop>
Tianpu
2015-08-26 23:43:07 +08:00
在同一个环境下,不考虑结果的正确性, stristr 的单次运行耗时是 0.0006ms

比例关系大致是:
stristr 1
pcre_stristr 7
mb_stristr 120

这个比例和看到的另外测试是一致的,应该是可靠的结果
vibbow
2015-08-26 23:44:06 +08:00
LZ 犯了一个错误,使用了忽略大小写的函数
PHP 忽略大小写的函数效率巨慢的
vibbow
2015-08-26 23:45:11 +08:00
之前 csdn 那事件的时候,我试过用 PHP 做全文搜索。

从 大小写不敏感 切换到 大小写敏感 的函数后

系统压力能从 CPU 转移到硬盘...
vibbow
2015-08-26 23:47:40 +08:00
当使用大小写敏感函数后:

C:\Users\vibbo\Desktop>php test.php
-----compatibility test-----
samples count: 1000
test finished

-----runtime test-----
mb_stristr () x1000
load in 0.01333ms

pcre_stristr () x1000
load in 0.02427ms

time save -82.07%
Tianpu
2015-08-26 23:48:40 +08:00
@vibbow 主要是不想还要检查是不是考虑了大小写

大小写敏感慢的话 很可能是一脉相承的慢 mb_convert_case 相关的都慢死 其它的只是一般的慢 stristr str_ireplace 这些都应该慢了

暂时我就使用 mb_*了 等有空 再整理数据改写下
vibbow
2015-08-26 23:49:37 +08:00
@Tianpu 大小写不敏感的速度和 mb 没关系
你用 PHP 原生的 strtoupper , stristr 之类的都很慢。
Tianpu
2015-08-26 23:53:58 +08:00
@vibbow 多谢

很可能找到根源了
PHP 和大小写相关的函数都是慢的

可是: stristr, strtoupper,ucwords,strtolower 又似乎是必须的
vibbow
2015-08-26 23:59:49 +08:00
我之前的做法是:
做两份文件,一份原始文件,一份全小写的文件。
搜索的时候,在全小写的文件里搜索,找到 index 后,从原始文件里截取出来。

就这样...
Tianpu
2015-08-27 00:05:02 +08:00
@vibbow 我只有一次写的需求,其实对速度要求也不是那么敏感

就是上午做了个自定义函数的自动测试,发现用到 mb_*都是 0.0xms+这个级别的,其它的都是 0.001ms-的时间消耗

然后就想弄清楚到底怎么回事,可能还是得自己维护个 alphabet ,简单的不长的字符串替换还是很快的,有限的文本总是有更多的办法来提升速度
realpg
2015-08-27 09:00:48 +08:00
@Tianpu
你想想大小写替换的本质,不就是把字符串进行字母个数各基本 replace 么……
肯定是倍数量级的速度
Zzzzzzzzz
2015-08-27 09:33:18 +08:00
mb_和不带 mb_的适用环境不同, mb_考虑到字符集的处理性能当然差了, 连 linux 下面常用的文本处理程序 locale 定义成 C 和 utf8 性能都能差几十到几百倍.
Zzzzzzzzz
2015-08-27 09:39:28 +08:00
上一段没说完, 你要处理的字符串不涉及其他字符集的话用不带 mb_系列挺好的, 涉及的话乖乖用 mb_, 不然的话可以把下一段保存成 gbk 运行一下看看

<?php
var_dump (strpos ("一二", "欢") === false );

var_dump (mb_strpos ("一二", "欢", 0, "GB18030") === false );

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/216212

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX