もぎゃ: 2013年5月アーカイブ

cakephpでModel->find('all'); をつかうと、検索結果を取得することができる。
この結果を
	$this->set('results',$this->Model->find('all'));
	$this->set('status','ok');
という具合にパラメタにセットして、
	protected function return_as_json(){
		$this->header('Content-Type: text/html');
		echo $this->indent( json_encode($this->viewVars) );
		exit();
	}
というような関数を呼び出してあげれば、検索結果をJSONで返すWebAPI的なものを作ることができる。

ところがこれがちょっと変で。JavaScriptからみた戻り値はこんなふうに見える。
{
    "results": [
        {
            "Model": {
                "id": "5",
                "user_id": "8",
                   :(略)
            }
        },
        {
            "Model": {
                "id": "4",
                "user_id": "8",
                   :(略)
            }
        },
   ],
    "status": "ok"
}
普通APIで検索結果を取得する時って、普通こうなってません?
{
    "results": [
        {
            "id": "5",
            "user_id": "8",
                   :(略)
        },
        {
            "id": "4",
            "user_id": "8",
                   :(略)
        },
    ],
    "status": "ok"
}

呼び出し側のJavaScriptから見たら、
function(res){//success
	var models = res['results'];
	for (var i = 0; i < models.length; i++) {
		console.log(models[i]['Model'].id)
	}
}
って謎の型名をつけるよりも、
function(res){//success
	var models = res['results'];
	for (var i = 0; i < models.length; i++) {
		console.log(models[i].id)
	}
}
のほうが自然ですよね。

前置きが長くなったけれど、そういうわけで型名を付けないで検索結果を返すようにする実装。
本当はjson_encodeするときに型名を落とすのが適切だと思うのだけれど、うまいやり方を思いつかなかったので、modelのカスタムfindとして定義してみた。
連想配列のまま構造を変えるのではなくて、一旦フラットにしてテキストとしてモデル名を除去しています。

allの代わりにnoModelNameを使えば、モデル名部分のないハッシュを得ることができます。
	$this->set('results', $this->Model->find('noModelName') );
	$this->return_as_json();


・同じ比較方法の場合、if文よりも三項演算子の方がやや速い ・もっとも高速な方法は論理和を使う方法 ・もっとも時間がかかる方法は型比較をif文で行う方法 ・null比較、型比較で三項演算子を利用すると真偽によって速度が(割と)変わる ( 変数の存在を確認する方法と速度比較(その2) - blog.katsuma.tv)

五年前の記事なのだけれど、関数に渡ってきた引数を存在チェックするとき、どう書くのが早いだろう?という実験レポート。
このレポートによると、

	var ret;
	if(arg) {
		ret = arg;
	} else {
		ret = 'bar';
	}
という比較的普通のコードと比べて
	var ret = (arg!=null)? arg : 'bar';
三項演算子を使うと倍近く早いらしい。
でも、変数の初期化だったら僕はこう書くことが多い。
	if(!arg) { arg = 'bar';}
ということで、五年経った現状と、僕のコードどうなんだろう、というのを見たいと思ったので試してみた。

Google Chrome 26.0.1410.65

[checkStrTernary]	1786
[checkStrIf]	1786
[checkArgsLogicalAdd]	 49
[checkArgsTernary]	 45
[checkArgsIf] 	51
[checkArgsIf2] 	48
[checkNullTernary] 	74
[checkNullIf] 	59
[checkTypeTernary] 	61
[checkTypeIf] 	48

待てw

やるんじゃないかとは思っていましたが、実質的に何もしていないことを見ぬいて最適化された結果、Date()の分解能テストと化しています。たぶんループが丸ごと削除されていますね。
もちろん、checkStrTernaryとcheckStrIf以外の順位は実施のたびに入れ替わりますので、個別のコードの有利不利を判定することはできません。

FireFox 17.0.1

[checkStrTernary]	14555
[checkStrIf]	14263
[checkArgsLogicalAdd]	 10572
[checkArgsTernary]	 10674
[checkArgsIf] 	11215
[checkArgsIf2] 	11258
[checkNullTernary] 	10659
[checkNullIf] 	10750
[checkTypeTernary] 	11102
[checkTypeIf] 	11714

うむ。さすが高機能JavaScript開発環境(僕命名)。
これを見ていると、やっぱりcheckStrTernaryとcheckStrIfが遅いものの、あとはそれほど大きな差じゃない程度になっています。checkArgsIfとcheckArgsIf2などは実施のたびに早いほうが入れ替わるので、誤差の範囲内です。

InternetExplorer 9.0.8112.16421

ログ: [checkStrTernary]	11868 
ログ: [checkStrIf]	11766 
ログ: [checkArgsLogicalAdd]	 8618 
ログ: [checkArgsTernary]	 8525 
ログ: [checkArgsIf] 	10521 
ログ: [checkArgsIf2] 	10767 
ログ: [checkNullTernary] 	10777 
ログ: [checkNullIf] 	10655 
ログ: [checkTypeTernary] 	11507 
ログ: [checkTypeIf] 	10584 

おおむねFireFoxと同じ傾向が出ています。よほど変な書き方をしない限り大差ないということですね。

所感

近年のブラウザにおいては、最適化が進んだ結果、以前ほど三項演算子有利ではなくなってきました。
それでも1割程度の差がつくので、シビアな場面ではトライする価値があるかもしれないですが、普通にコード書くときは、読みやすいほうを使うのでいいんじゃないかなーと思いました。

コード:



このアーカイブについて

このページには、 もぎゃ < /strong>が 2013年5月 に書いたブログ記事が含まれています。

前のアーカイブは もぎゃ: 2013年4月 です。

次のアーカイブは もぎゃ: 2013年6月 です。

最近のコンテンツは インデックスページ で見られます。過去に書かれたものは アーカイブのページ で見られます。

Powered by
Movable Type