シングルトンパターンをクロージャで実装するとオーバーヘッドは減るのか

Life is beautiful: Python Hack : 噛めば噛むほどおいしくなるクロージャの話にて、クロージャを使ってスコープの小さなシングルトンパターンを実装する話が書かれていました。

「if not _config:」という条件分岐を毎回毎回実行しなければならないこと。一つ一つは小さな話でも、何百回も何千回も呼ぶ必要がある場合、このオーバーヘッドも馬鹿にならない(人間だったらすぐに気がついてチェックを辞めるが、プログラムの場合は素直に何度でもチェックしてしまうから)

http://satoshi.blogs.com/life/2009/11/python-hack.html

とあるように、通常シングルトンパターンを実装するときは、インスタンスをロード済みかどうかを毎回チェックする必要があります。

純粋にどのくらいオーバーヘッドがあるのか気になったのと、普段このような実装をしていて無駄だよなぁ…と思っていたので、実際に計測してみました。とりあえず手軽にクロージャが使えるというところでJavascriptで実装しています。

ロード済みかチェックパターン

var Singleton = {
	get:function(){
		if(!this.instance)
			this.instance = {};
		return this.instance;
	}
}
var start = new Date();
for(var i = 0; i < 1000000; i++) {
	Singleton.get();
}
alert(new Date() - start);

クロージャを使ったパターン

var Singleton = {
	get:function(){
		var instance = {};
		this.get = function() { return instance; }
                return this.get();
	}
}
var start = new Date();
for(var i = 0; i < 1000000; i++) {
	Singleton.get();
}
alert(new Date() - start);

計測結果

それぞれ100万回の試行を3回行いその平均値を取りました。その結果は…。

ロード済みかチェックパターン 1746 msec
クロージャを使ったパターン 1669 msec

ということで、その差77msec。わずかではありますが、クロージャを使ったほうが早い。とはいえ、バカにならない程度ではないですね。まぁ、nullチェックなんてそんなもんかと一安心(目をつぶれないほどの差があったら持病の書き直したい病が発病するところだった!) とりあえず、"Javascriptでは"。

逆に、クロージャを使ったほうが遅くなるということはないので、ロード済みのインスタンスを隠蔽できる分優秀ということになりますね。あぁすっきりした。