defsubとluasubのベンチマーク比較

久々のベンチマークネタ。
同じ結果の出る*1関数をdefsubとluasubの二つを用意して、それぞれを実行してその速度を比較した。

詳細

defsub側は、sqrt, sqrt2, sqrt3の三つを用意した。スクリプトは、平方根の計算 - 永字八法を使用した。
luasub側は、同じ結果になるsqrt_lua, sqrt_lua2, sqrt_lua3の三つを用意した。
それぞれの関数について、1〜10,000までを順番に計算し、どれくらいの時間がかかるかを計測した。

結果

sqrt,43514
sqrt2,62338
sqrt3,77410
sqrt_lua,1953
sqrt_lua2,2003
sqrt_lua3,2024

考察

sqrtに関しては明らかにluaに処理を移譲した方が早いね。

使用したスクリプト

00.txt
*start

csvopen "bench.csv","w"

resettimer
for %0=1 to 10000
	sqrt %1,%0
next
gettimer %10
csvwrite "sqrt",%10

resettimer
for %0=1 to 10000
	sqrt2 %1,%0
next
gettimer %10
csvwrite "sqrt2",%10

resettimer
for %0=1 to 10000
	sqrt3 %1,%0
next
gettimer %10
csvwrite "sqrt3",%10

resettimer
for %0=1 to 10000
	sqrt_lua %1,%0
next
gettimer %10
csvwrite "sqrt_lua",%10

resettimer
for %0=1 to 10000
	sqrt_lua2 %1,%0
next
gettimer %10
csvwrite "sqrt_lua2",%10

resettimer
for %0=1 to 10000
	sqrt_lua3 %1,%0
next
gettimer %10
csvwrite "sqrt_lua3",%10

csvclose
end

*define

mov %0,100
numalias sqrt_res,%0:inc %0 ; 平方根を返す数値
numalias sqrt_base,%0:inc %0 ; 平方根を求めたい数値
numalias sqrt_temp,%0:inc %0 ; 計算用変数
numalias sqrt_power,%0:inc %0 ; 二乗用変数

defsub sqrt
defsub sqrt2
defsub sqrt3
game

;==================
; sqrt
;==================
; 平方根を求める。
; 第一引数:結果の平方根を格納する数値変数
; 第二引数:平方根を求めたい数値(変数)
; 平方根を返すが、端数が切り捨てられるので非常に精度が悪い。
*sqrt
getparam i%sqrt_res,%sqrt_base
mov %%sqrt_res,0 ; 設定する。
if %sqrt_base<1 return ; 負の数値は受け付けません。
mov %sqrt_temp,%sqrt_base ; 仮に置く。
*sqrt_loop
mov %sqrt_power,%sqrt_base/%sqrt_temp ; 仮の数値で元の数値を割ってみる。
notif %sqrt_power<%sqrt_temp mov %%sqrt_res,%sqrt_temp:return ; これが回答。返す。
mov %sqrt_temp,(%sqrt_temp+(%sqrt_base/%sqrt_temp))/2 ; ニュートン法による計算。
goto *sqrt_loop

;==================
; sqrt2
;==================
; 平方根を求める。ただし、結果は10倍された数値になる。
; 第一引数:結果の平方根を格納する数値変数
; 第二引数:平方根を求めたい数値(変数)
*sqrt2
getparam i%sqrt_res,%sqrt_base
sqrt %%sqrt_res,%sqrt_base*100
return

;==================
; sqrt3
;==================
; 平方根を求める。ただし、結果は100倍された数値になる。
; 第一引数:結果の平方根を格納する数値変数
; 第二引数:平方根を求めたい数値(変数)
*sqrt3
getparam i%sqrt_res,%sqrt_base
sqrt %%sqrt_res,%sqrt_base*10000
return
system.lua
NSExec("luasub sqrt_lua")
function NSCOM_sqrt_lua()
	local ret = NSPopIntRef()
	NSPopComma()
	local val = NSPopInt()
	NSSetIntValue(ret, math.floor(math.sqrt(val)))
end
NSExec("luasub sqrt_lua2")
function NSCOM_sqrt_lua2()
	local ret = NSPopIntRef()
	NSPopComma()
	local val = NSPopInt()
	NSSetIntValue(ret, math.floor(math.sqrt(val)*10))
end
NSExec("luasub sqrt_lua3")
function NSCOM_sqrt_lua3()
	local ret = NSPopIntRef()
	NSPopComma()
	local val = NSPopInt()
	NSSetIntValue(ret, math.floor(math.sqrt(val)*100))
end

*1:スクリプトで1から10,000までは確認済