str_replaceとpre_replace、文頭マッチはstrpos2個で?
2009/06/04 (Thu) 06:12:33
紅堂幹人

紅堂幹人ういや、メタルなMacBookにしてからBenchmarkやらしてないし、PEAR入れてねぇや、とPEAR入れてベンチしてみる。置換系とか気にせずpreg_replaceメインでガジガジ書いてたので、改善せんとなぁ、と。$str = "gaogao\thoge\rfuga\naaaaaaaaaragaga";として、str_replace(array("\r", "\n", "\t"), '', $str);は「2.430213」で一番早い。それぞれ置換後を別にする場合のstr_replace(array("\r", "\n", "\t"), array('', '', ''), $str);は「3.119805」でstrtr($str, array("\r"=>'', "\n"=>'', "\t"=>''));は「3.187766」掛かる。strtrで連想配列置換は置換前・置換後が違う場合で、沢山あって可読性を高めたい場合使うべき。preg_replace("/\r|\n|\t/", '', $str);と今まで使ってきていたのは一番効率が悪く、「19.906528」掛かる。正規表現が必要な場合以外、preg_replaceは無駄だ。preg_replaceがここまで遅いとは、知らなかったorz 文字列が含まれるか調べる際のpreg_matchもstrposの方がそりゃ良いわけでただ、複数条件記述してのmatchはやっぱりpreg_matchの方が書き易いし、見易い。strposでarrayは使えないし、一旦配列に入れてforeach内でstrposするのもコストが掛かるから、やっぱりpreg_matchだ。1つ目の判定で正規表現が必要でpreg_matchを使うからと、正規表現が必要も無いのについ2つ目の判定もpreg_matchを使っていた、なんてことはありがちだ。あと、preg_match("/^gaogao/", $str)で文頭マッチさせたいだけなら「strpos($str, "gaogao") == 0」で判別すべきとかか。いや、「 && strpos($str, "gaogao") !== false」て加えないと正しく判定しないから長くなるし処理上変かな。てかstrncasecmp()使おうよ← preg_matchは「1.437134」で、strpos2個判定(つまり『strpos($str, "gaogao") == 0 && strpos($str, "gaogao") !== false』判定)は「1.164024」で『strpos && strposの方が早い』という結果になった。かといって、文頭マッチ用にユーザ定義関数を作るとコストが「1.918008」とpreg_matchよりも掛かる事になるので本末転倒だ。で、strncasecmp($str, 'gaogao', 6) == 0だと「1.060319」でベスト。きちんと考えてstrncasecmpで書くようにしなくちゃ、いつまで経っても公開できないぞ、と戒める。
 preg_match("/Firefox|Opera|Macintosh|Safari/", $_SERVER['HTTP_USER_AGENT'])とif文判定したいだけなのにstrpos($_SERVER['HTTP_USER_AGENT'], 'Firefox') !== false || ...と4つも書くのは長ったらしいからやめとこう、と。この場合は速度犠牲にしても可読性を上げるべきでしょう。
 file()やfile_get_contents()が便利だなー、とつい使ってしまいがちだけれど、一行カウンタなら$fp = fopen('~', 'r+');でfgetsしてfseek($fp, 0, SEEK_SET);でファイルポインタ頭にしてfwriteした方が良い、とか。1行で0から書くならftruncate($fp, 0);も書いとくか。fileで配列に読むと「7.360804」file_get_contentsで変数に読むと「6.948488」fopenでやると「2.523558」と、かなり違いが出たり。アルゴリズムきちんと考えて書きましょう、と。
 呑み→静岡県 花の舞(吟醸酒)

この記事のURL
http://galle.oe-p.com/cgi-bin/diary_01.cgi?category=diary&anchor=090604
カテゴリ:日記 / この記事のURL / コメント(0)