osライブラリのclockはベンチマークデバッグに利用できるので、osライブラリではなく、あえて、こちらに入れておく。
local x = os.clock() -- この行に来た瞬間のCPU時間 local s = 0 for i=1, 100000 do s = s + i end print(string.format("elapsed time: %.2f\n", os.clock()-x ))
関数に関する情報を格納したテーブルを返します。
f の値として、関数を直接渡すか、 数値を指定することができます。
''数値は指定したスレッドのコールスタック上で実行中のレベル f の関数を表します。
レベル 0 は現在の関数 (getinfo 自身) で、レベル 1 は getinfo を呼んだ関数で、以下同様です。''
(スタックにカウントされない末尾呼び出しを除きます)。そうでなければ、date は現在時刻を書式化する。
format が `!´ で始まっていたら、日付は世界時 (Universal Time) で書式化される。
このオプション文字の後、 format が *t であれば、 date は以下のフィールドを持つテーブルを返す。
プロパティ 意味 source 関数の定義位置。 short_source sourceの短縮形。(今ひとつ存在意義は謎) linedefined 該当関数が定義されている行 lastlinedefined 該当関数が定義されている最後の行 what 関数の種類。"Lua"か"C"、メインチャンクの場合は"main"
debug.getinfo(print).what --> "C"
debug.getinfo(myfunc).what -->"Lua"
i = loadstring("return 3")
debug.getinfo(i).what --> "main"name 関数の妥当と思われる名前。数値を指定してgetinfoを呼び出した場合のみ機能する。 namewhat nameフィールドの種類。対象の関数が何者か。"global", "local", "method", "field", ""(空文字) nups 関数が持つ上位値の数。レベルと関連。 activelines 関数のアクティブ行の集合のテーブル。デバッガでも作らない限り、まぁあまり気にしなくても良い。 func 関数自身。これだけだと、一見無意味に思えるが、該当レベルで関数がアクティブだったらここに入るというフィルターがかかっている。
スタック上のレベル f の関数のインデックス local のローカル変数の名前と値を返します。 明示的なローカル変数だけでなく、 引数や一時変数などにもアクセスします。
最初の引数またはローカル変数はインデックス 1 で、 最後のアクティブな変数まで以下同様です。
負のインデックスを指定すると可変長引数を参照します。
'-1' は最初の可変長引数です。指定したインデックスの変数が存在しなければ nil を返し、
範囲外のレベルを指定した場合はエラーを発生します。 (レベルが有効かどうかを調べるには debug.getinfo を使ってください。)
'(' (開き括弧) で始まる変数名は内部の変数 (ループ制御変数、 一時変数、 可変長引数、 および C の関数のローカル変数) を表します。
引数 f に関数を指定することもできます。この場合は関数の引数の名前だけを返します。function foo (a, b) local x do local c = a-b end local a = 1 while true do local name, value = debug.getlocal(1,a) if not name then break end print(name, value) a = a + 1 end end foo(10, 20) --[[ a 10 b 20 x nil a 4 ]]
debug.getlocalの第3パラメータには、該当の変数に設定する値を指定できる。
local name, value = debug.getlocal(1, var_index, 5)とすると、name, varには元の変数の名前と値が返ってくるが、該当の変数の値自体は5になっている。
message が文字列でも nil でもなければ、それ以上の処理をせずに message を返します。
そうでなければ、 スタックトレースの文字列を返します。
省略可能な文字列 message がトレースの先頭に追加されます。
省略可能な数値 level はトレースを開始するレベルを指定します。
(デフォルトは 1 で、 traceback を呼んだ関数です)co = coroutine.create( function() local x = 10 coroutine.yield() error("some error") end) coroutine.resume(co) print(debug.traceback(co)) --> yieldでとまっている状態でコルーチンをトレース print(coroutine.resume(co)) print(debug.traceback(co)) -- > エラーが発生した後にコルーチンをトレース print(debug.getlocal(co,1,1)) -- > エラーが発生した後でもローカル変数は調査可能 --[[ 実行結果: stack traceback: [C]: in function 'yield' c:\test.lua:3: in function <c:\test.lua:1> false c:\a.lua:4: some error stack traceback: [C]: in function 'error' c:\test.lua:4: in function <c:\test.lua:1> x 10 みたいな形。 ]]
指定された関数にフックを設定する。 文字列 mask と数値 count は、いつフックが呼ばれるかを記述する。 文字列 mask には以下の文字を指定する
mask 意味 c フックはLuaが関数を呼ぶたびに呼ばれる。 r フックはLuaが関数から戻るたびに呼ばれる。 l フックはLuaがコードの新しい行に入るたびに呼ばれる。
count がゼロでなければ、フックは count 命令が実行されるたびに、その直後に呼ばれる。引数なしで呼ぶとフックは無効になる。
フックが呼ばれたとき、最初の引数はフックを起動したイベントを示す以下のいずれかの文字列である。 "call", "return" "tail return", "line", "count"。
lineイベントの場合、フックは二番目の引数に新しい行番号が得られる。
"tail return" を除いて、 フックの内部でレベル2の getinfo を呼べば、実行中の関数に関する情報をもっと得られる
( レベル0は getinfo 関数自身で、レベル1はフック関数である。)
( "tail return" はLuaが復帰をシミュレートしているだけであり、 getinfo は正しくないデータを返す。)
function hook_func(p) local fname = debug.getinfo(2).name print("[hook]"..p..":"..fname) end debug.sethook(hook_func, "c") -- call function function hoge1(a,b) return a,b end function hoge2(a,b) return a,b end hoge1(3,5) hoge2(1,2) --[[ 実行結果 [hook]call:hoge1 [hook]call:hoge2 --]]
local Counters = {} local Names = {} local function hook() local f = debug.getinfo(2, "f").func if Counters[f] == nil then Counters[f] = 1 Names[f] = debug.getinfo(2, "Sn") else Counters[f] = Counters[f] + 1 end end local f = assert(loadfile(arg[1])) debug.sethook(hook, "c") f() debug.sethook() function getname(func) local n = Names[func] if n.what == "C" then return n.name end local lc = string.format("[%s]:%s", n.short_src, n.linedefined) if n.namewhat ~= "" then return string.format("%s (%s)", lc, n.name) else return lc end end for func, count in pairs(Counters) do print(getname(func), count) end
function abc() return 3 end abc() abc() abc() abc()
実行 lua profile.lua test.lua 実行結果 sethook 1 [test.lua]:1 (abc) 4 [test.lua]:0 (f) 1