以下の様な2つの書き方、皆さんしていませんか?
1.for(i = 0; i < strlen(文字列変数); i++)
2.for(i = 0; i < count(配列変数); i++)
strlen(
マニュアル)は文字列のバイト数(文字数ではない)をint型で返す関数で、
count(
マニュアル)は配列の要素数などをint型で返す関数です。
詳細はマニュアルを参照して下さい。
で、実は上記の書き方。
ループを終了するかどうか判断する際に、「必ず」関数が実行されます。
なので、その分多くの処理が実行され、
結果としてコストがかかるわけです。
関数内でバイト数や要素数を求めている以上。
よって、上記の文字列変数や配列変数の中身を、
ループ内で編集したり「しない」ならば、
必ず実行するのは無意味というか無駄なわけです。
バイト数や要素数がループ内で増減するのであれば、
上記の書き方で良いのですが。
そこで、strlenなどを「for文の1行上に書く」という方法を提案します。
以下は、コストをマイクロミリ秒単位で計測したサンプルプログラムです。
環境はOSはFedora12で、PHPのバージョンは5.3.0です。
1.for文の中にstrlen関数を書いた場合
--------------------------------------------------------------------------------
<?php
function microtime_float() {
list($usec, $sec) = explode(' ', microtime());
return ((float)$usec + (float)$sec);
}
$time_start = microtime_float();
for($i = 0; $i < strlen('11'); $i++) {
}
$time_end = microtime_float();
$time = $time_end - $time_start;
echo $time . ' seconds' . "\n";
?>
結果例:
[root@www ~]# for i in 1 2 3 4 5 6 7 8 9 10; do php for_test_in.php; done
6.6995620727539E-5 seconds
6.6041946411133E-5 seconds
6.6041946411133E-5 seconds
6.4849853515625E-5 seconds
7.3909759521484E-5 seconds
6.4849853515625E-5 seconds
6.4849853515625E-5 seconds
7.5101852416992E-5 seconds
6.6041946411133E-5 seconds
7.1048736572266E-5 seconds
[root@www ~]#
--------------------------------------------------------------------------------
2.for文の外にstrlen関数を書いた場合
--------------------------------------------------------------------------------
<?php
function microtime_float() {
list($usec, $sec) = explode(' ', microtime());
return ((float)$usec + (float)$sec);
}
$time_start = microtime_float();
$length = strlen('11');
for($i = 0; $i < $length; $i++) {
}
$time_end = microtime_float();
$time = $time_end - $time_start;
echo $time . ' seconds' . "\n";
?>
結果例:
[root@www ~]# for i in 1 2 3 4 5 6 7 8 9 10; do php for_test_out.php; done
6.6041946411133E-5 seconds
6.6041946411133E-5 seconds
0.00010585784912109 seconds
0.0001070499420166 seconds
6.5088272094727E-5 seconds
6.5088272094727E-5 seconds
7.3909759521484E-5 seconds
7.6055526733398E-5 seconds
6.6041946411133E-5 seconds
8.2969665527344E-5 seconds
[root@www ~]#
--------------------------------------------------------------------------------
3.for文の中にcount関数を書いた場合
--------------------------------------------------------------------------------
<?php
function microtime_float() {
list($usec, $sec) = explode(' ', microtime());
return ((float)$usec + (float)$sec);
}
$array = array();
for($j = 0; $j < 2; $j++) {
$k = strval($j);
$array[$k] = $k;
}
$time_start = microtime_float();
for($i = 0; $i < count($array); $i++) {
}
$time_end = microtime_float();
$time = $time_end - $time_start;
echo $time . ' seconds' . "\n";
?>
結果例:
[root@www ~]# for i in 1 2 3 4 5 6 7 8 9 10; do php for_test_array_in.php; done
4.4107437133789E-5 seconds
4.4822692871094E-5 seconds
5.5074691772461E-5 seconds
7.1048736572266E-5 seconds
4.3869018554688E-5 seconds
5.9127807617188E-5 seconds
4.3869018554688E-5 seconds
4.4107437133789E-5 seconds
5.1975250244141E-5 seconds
4.3869018554688E-5 seconds
[root@www ~]#
--------------------------------------------------------------------------------
4.for文の外にcount関数を書いた場合
--------------------------------------------------------------------------------
<?php
function microtime_float() {
list($usec, $sec) = explode(' ', microtime());
return ((float)$usec + (float)$sec);
}
$array = array();
for($j = 0; $j < 2; $j++) {
$k = strval($j);
$array[$k] = $k;
}
$time_start = microtime_float();
$length = count($array);
for($i = 0; $i < $length; $i++) {
}
$time_end = microtime_float();
$time = $time_end - $time_start;
echo $time . ' seconds' . "\n";
?>
結果例:
[root@www ~]# for i in 1 2 3 4 5 6 7 8 9 10; do php for_test_array_out.php; done
4.1961669921875E-5 seconds
4.3869018554688E-5 seconds
4.5061111450195E-5 seconds
5.2213668823242E-5 seconds
6.8187713623047E-5 seconds
7.2002410888672E-5 seconds
4.2200088500977E-5 seconds
4.1961669921875E-5 seconds
4.1961669921875E-5 seconds
4.1961669921875E-5 seconds
[root@www ~]#
--------------------------------------------------------------------------------
で、上記4つのプログラムをそれぞれ100回実行した時の、
平均速度が以下です。
プログラムのパターン |
100回実行時の平均速度 |
1.for文の中にstrlen関数を書いた場合 |
0.0000736秒 |
2.for文の外にstrlen関数を書いた場合 |
0.0000746369秒 |
3.for文の中にcount関数を書いた場合 |
0.0000503135秒 |
4.for文の外にcount関数を書いた場合 |
0.0000476432秒 |
微妙な結果です。
では、上記では「2」だったバイト数と要素数を、
それぞれ「100」に変更して実行した結果が以下です。
プログラムのパターン |
100回実行時の平均速度 |
1.for文の中にstrlen関数を書いた場合 |
0.000111005秒 |
2.for文の外にstrlen関数を書いた場合 |
0.0000818014秒 |
3.for文の中にcount関数を書いた場合 |
0.00007671秒 |
4.for文の外にcount関数を書いた場合 |
0.000055秒 |
予想通り、for文の外に書いた方がコストがかからないという結果が出ました。
結果はほんの僅かの差ですが、
システムやアプリの性能改善で、
「色々チューニングしてみたけど、要望まであとちょっと足りない!」などの時に、
やってみるのは如何でしょうか。
特にcountの方は要素数100以上などはザラにあるでしょうし、
for文自体、頻繁に使うものですし。
塵も積もれば山となるとも言いますしね。
とはいえ、デグレが恐いのも確かです。
なので、プログラムを書く際に「習慣的」にやっておけば、
「少なくても、for文の部分に関してはチューニングの余地無し」となり、
精神的な心配からは開放されるのではないかと思います(笑)
他言語は現時点では不明です。
JavaScriptだと、文字列or配列のlengthプロパティなど。
Javaだと、Stringクラスのlengthメソッド、配列のlength属性、
Collectionインターフェースのsizeメソッドなどが対象でしょうか。
取り上げるかどうかは・・・不明ですが。
スポンサーサイト
テーマ:日記 - ジャンル:日記
- 2010/07/25(日) 18:47:20|
- PHP
-
| トラックバック:0
-
| コメント:3