Edited at

[php]速度比較シリーズ -比較演算子(暗黙の型変換)-

More than 1 year has passed since last update.

いつもはPHPerなまみーです。

勝手に始めてみました「速度比較シリーズ」

第一弾は、主に新人向けに「暗黙の型変換」をある程度可視化してみます。


概要

普段何気なく使っている(かもしれない)比較演算子。

レガシーなコードを追いかける現在、ほんと気になって仕方がない。

なので雑に比較してみようと思います。

よく見るのはこんなやつです。

$hoge === 0

$hoge == 0
$hoge == '0'

どれに統一したらいいの!


比較演算子で速度比較

暗黙の型変換をする場合、しない場合の処理速度を、if文を使って比較します。

単純に比較するのみです。


計測プログラム

イケてないコード - Webエンジニアのブログ さんの

PHP速度対決!差が出る5パターン

こちらのコードをそのまま使わせて頂いております。

No.2 のバリエーションを増やしてみました、という形になります。


average.php

<?php

//計測回数
define('COUNT',10);
//試行回数
define('TEST_COUNT',100000);
//小数点桁数
define('DECIMAL_DIGITS',10);
//平均値
$average = 0.0;

//テスト用変数
$num_str='0';
$num_int=(int)$num_str;

echo("## (int)\$num_str === 0 \n");
//10回計測するよ
for($i = 0; $i < COUNT; $i++) {
//1回分の計測開始時間
$start = microtime(true);

//10万回計測するよ
for($j = 0; $j < TEST_COUNT; $j++) {
// ここにif文+比較演算子を書くよ
}

//1回分の計測終了時間
$end = microtime(true);
$result = $end - $start;
echo ' '.number_format($result,DECIMAL_DIGITS)."秒\n";
$average += $result;
}

//平均値の出力
$average = number_format($average/COUNT,DECIMAL_DIGITS);
echo ' average:'. $average."秒\n";



計測方法


  • 10万回実行した時間を計測

  • さらに10回繰り返した平均値を比較


動作環境

項目
スペック

php
5.6.29

os
Amazon Linux AMI release 2016.09

cpu
Intel(R) Xeon(R) CPU E5-2670 v2 @ 2.50GHz

core
2

mem
8GB


結果


前提

//テスト用変数

$num_str='0';
$num_int=(int)$num_str;


計測結果

No.
構文
暗黙の型変換
処理時間[s]

1
$num_int === 0
なし
0.0046874523

2
$num_int == 0
なし
0.0045311689

3
(int)$num_str === 0
なし
0.0076557159

4
$num_str === '0'
なし
0.0049149036

5
$num_str == '0'
あり
0.0094812632

6
$num_str == 0
あり
0.0071495533

番外編
'3abc' == 3
あり
0.0074138165


解説


1.あらかじめキャストしてから、型変換なしの比較

型変換されないので早い。

if( $num_int == 0 ) {...}


2.あらかじめキャストしてから、型変換なしの比較

型変換されないので早い。

if( $num_int === 0 ) {...}


3.毎回キャストしてから、型変換なしの比較

キャストしてる分遅い。

if( (int)$num_str === 0 ) {...}


4.文字列同士、型変換なしで文字列での比較

型変換しないので早い。

if( $num_str === '0' ) {...}


5.文字列同士、型変換が生じない比較

右辺か左辺が文字列で、暗黙の型変換の式の場合は遅いのかもしれない。

if( $num_str == '0' ) {...}


6.文字列と整数、暗黙の型変換が生じる比較

暗黙の型変換が実行されるから遅い。

if( $num_str == 0 ) {...}


番外編.文字列の1文字目が整数で、2文字目以降が整数以外と整数、暗黙の型変換が生じる比較

暗黙の型変換が実行されるから遅い。

かつ、 暗黙の型変換は、文字列の最初の数値部分を(int)でキャストした値になる ため、以下の構文が "true" になってしまいます。

if( '3abc' == 3 ) {

echo 'true';
}

ここは別エントリーにしたいですね。


結論


  • 型があっているのが一番早い

  • でも変数が文字列だとコストがかかっている(倍以上)


    • 右辺か左辺が文字列で、暗黙の型変換の式の場合



  • 暗黙の型変換はコストがかかっている(倍以上)

  • ビール最高!(IPA)


まとめ


  • 型は合わせるのがベスト

  • 変数で型を変化させるのはやめよう


    • フラグとか



  • とはいえ誤差の範囲とも言える


所感

ちょっとした工夫が大きな結果になりかねません。

塵も積もれば山となる、の精神で。

今回は誤差の範囲と言えるかもしれませんが、こういう思考でコードを書くのは大事かな、と思いました。

エンジニアは 「普通の人より深く物事を考える」 のが仕事とも言えるので。


(おまけ)これはやめたい


どうせ整数しか入らないから、文字列でも数値でも同じ比較しちゃおう

定数にしようとかレビューはどうしたとか色々ありますけど。

統一できるなら型は合わせたいですね。

(何か処理)

if( $hoge_result == true ) {
$ret_code = 0;
}

(何か処理)
if( $fuga_result == false ) {
$ret_code = '1';
}


課題


ひとこと

みんなカジュアルに速度比較しようぜ!

つっこみどころありましたら、コメントなど頂けたら嬉しいです。 m(_ _)m