0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【PHP】mb_substr()は遅い

Posted at

環境

PHP:7.1.21

内容

下記のような処理がありました(簡素化してます)。

入力された文字列を、mb_substr() で1文字ずつ切り取ってチェックしていました。
処理速度に問題はありませんでした。

//住所・氏名など
$src = '入力された文字列';

$count = mb_strlen($src);

//1文字ずつチェック
for ($i=0; $i<$count; $i++) {
    $moji = mb_substr($src,$i,1);
}

ある日、上記処理に、100KB以上の文字列を渡しました。
するとタイムアウトが発生しました。

Fatal error: Maximum execution time of xx seconds exceeded in /foo/bar/xxxx.php on line xxx

何でそんなに時間かかるの? と思いましたが、
原因を推測すると、こういうことなんじゃないかと。

mb_substr() は何かしら文字コード変換をおこなうのですが、
「1文字 切り取って文字コード変換」ではなくて、
「文字列全部をコード変換して、1文字 切り取る」なのでしょう。

つまり、上記処理にマルチバイトの 100,000文字が渡されたら、

100,000文字 x 100,000ループ = 10,000,000,000文字

100億文字のコード変換をおこなうことになります(推測ですが)。
(100億文字は Shift_JIS だと約20GBかな?)

文字数の2乗に比例して遅くなる計算です。
そりゃタイムアウトになります :sob:

ちなみに上記処理の mb_substr() を substr() にすると、一瞬で完了します。
やはりマルチバイトの処理で時間がかかっているようです。

さいごに

mb_substr() が遅いというより、私の使い方に問題があるとも言えます。

ちなみに100KB以上の文字列を、分割して数回に分けて渡したら、
タイムアウトはしなくなりました。

参考

mb_substrが遅い

0
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?