这几天被wp-kit-cn(中文工具箱,wordpress插件)的一个内存溢出问题搞得满头头皮屑……在处理大文本的时候,它原有的计算字数的算法会占用巨大的内存,基本上超过5万汉字就不用期待能够给我返回一个正确的结果。在这个插件中,它使用正则匹配的方式来取得一段文字的实际长度,代码如下:
Language: PHP
return preg_match_all('%(?: [\x09\x0A\x0D\x20-\x7E] # ASCII | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 )%xs',$text,$out);
代码中所做的事情就是匹配所有的字符,然后只使用其中正确匹配的数目,而对匹配结果直接丢弃,而这直接代表着性能的严重损耗以及效率的降低,我翻了翻我几年前根据网上类似的代码整理出来的函数取代了它的这条语句:
Language: PHP
return strlen(preg_replace("/[\xc2-\xdf][\x80-\xbf] |\xe0[\xa0-\xbf][\x80-\xbf] |[\xe1-\xef][\x80-\xbf]{2} |\xf0[\x90-\xbf][\x80-\xbf]{2} |[\xf1-\xf7][\x80-\xbf]{3}/","1",$text));
我做的事很简单:把所有的非ascii字符全部替换成1个ascii字符(就是数字1),接下来要做的就是直接算它的长度,嗯,完成了。我不知道我的这个性能如何,我只知道现在我的索引页不会再次出现Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 44 bytes) …
之类严重的错误。



支持,顶一下。
[回复]