※注 タイトルには string:byte とありますが、どちらかというとLua自身の話だと思います。
文字列を内部コードに変換するとき、 hoge = { string:byte(1,-1) }
という記述をすると文字列を一気に配列にしてくれて便利なのですが、この書き方だと結構遅いことに気づきました。
実行環境
LuaJIT 2.1.0-beta1
例
たとえば、文字列を1文字ずつ変換してtableの配列にぶちこむロジックなのですが
- 1文字ずつ実直にループしてtable化
-
{ string:byte }
形式
という2パターンで比較してみました。
以下の様なスクリプトです。
-- display time
function time(title, block)
local st = os.clock()
block()
local ed = os.clock()
print(title .. ": " .. ed-st.. " sec")
end
-- 速い
local function _string2bytearray_fast(data)
local i = 1
local t = {}
for i=1, string.len(data) do
t[i] = data:byte(i)
end
return t
end
-- 遅い
local function _string2bytearray_slow(data)
return { data:byte(1, -1) }
end
-- 変換する文字列
msg = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
-- ロジックチェックしとく
assert(_string2bytearray_fast(msg) ~= _string2bytearray_slow(msg), "_string2bytearray_fast != _string2bytearray_slow")
----------------------------------------------------------------------
-- bench 1
time("_string2bytearray_fast", function()
for i=0, 1000000 do
local tmp = _string2bytearray_fast(msg)
end
end)
-- bench 2
time("_string2bytearray_slow", function()
for i=0, 1000000 do
local tmp = _string2bytearray_slow(msg)
end
end)
結果は以下のとおりです。
$ /opt/openresty/luajit/bin/luajit bench.lua
_string2bytearray_fast: 1.3 sec
_string2bytearray_slow: 31.54 sec
30倍?ほど遅い計算になります。
こちら、おそらく hoge = { (配列返す関数) }
という記述をした時の話なのでしょうか?
コードは詳細に追ってないのですが、どうしてここまで違うのかはちょっと気になりますね。