luaの内部最適化について
これメモリ確保してる?無駄に新しいの生成してない?など、luaの内部挙動についてマニュアルを見ても不明だった点を2,3書き残しておきたいと思います。
内部処理は今風でとても賢いです:Q
文字列の受け渡し
luaの引数の説明では「参照渡しされるのはテーブル」と表記されていて文字列に関しては明記されていません。てっことはもしかしてコピーされちゃうの?
というわけで、allocをフックしてメモリ確保の流れをログします。
local str = "test case !!!!!!!!!!!!!!!!" custom.alloclog(true) testcall(str) print(str) custom.alloclog(false) function testcall(str) print(str) end
custom.alloclog()はメモリ確保、解放ログ出力の自前命令、仮命令です。関数の呼び出し時にコピーされるか確認します。
一応参照渡しチェックと言うことで、元strの内容も出力しておきましょうか。
test case !!!!!!!!!!!!!!!! test case !!!!!!!!!!!!!!!!
メモリ確保ログが出ないのでコピーされていません。”低レベル層”では参照渡しがされているのがわかります。
というわけで内部で連結してみましょう。
function testcall(str) str = str.."hoge!" print(str) end
ptr:20890C0 osize:133 nsize:138 usage:244K ptr:23AB9B0 osize:4 nsize:155 usage:244K test case !!!!!!!!!!!!!!!!hoge! test case !!!!!!!!!!!!!!!!
内部連結分の確保が現れましたが大元strの内容はちゃんと維持されますので、”高レベル層”では値渡しでコピーされているかのような振る舞いです。
ちゃんと今風な言語の文字列の動き(値渡しのような振る舞いが出来る文字列)で賢い文字列でした。ありがたい!
文字列においては変更が無い限り生成が発生しないので、数字などと同じコスト(リスク無し)で渡せます。
なので、
function hogeclass:getdata() return self.data end function hogeclass:setdata(d) self.data = d end
というような、dataが100MBをこえる大きなバイナリデータのやりとりにgetter/setterを挟んでもコストが発生することはありません。安心安全。今すぐインストールです。
おまけ。
luaコンパイルにはちゃんと固定値(const)判断っぽいようなのもあるようで、
custom.alloclog(true) local str = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" custom.alloclog(false)
このコードが実行されるときに"aaaaaaa...."のメモリが確保されることはありません。低レベル層では固定値"aaaaaaaaaaa...."の参照渡しで処理されます。
なので、関数の外に固定値として「const_name="hogehoge"」として宣言しなくても最適化してくれるようです。
ただし、テーブルはその限りではありませんのでご注意ください。
functionのキャッシュ
次はfunctionのコンパイル挙動について。
自分がよく使って怒られる、関数内関数みたいなものの場合のコストについてです。
function hoge(x1) function inhoge(x1,x2) return x1*x2 end return inhoge(x1+1,x1+2) end
もうちょっと低レベルに展開すると
function hoge(x1) local inhoge = function(x1,x2) return x1*x2 end return inhoge(x1+1,x1+2) end
となり、inhogeに無名関数が突っ込まれる形になります。こうしてみると、hoge()が呼ばれるごとにinhoge()のコンパイルが発生しそうですよね。
それを調べるためにinhoge()の関数ポインタを出力させます。
function hoge(x1) local inhoge = function(x1,x2) return x1*x2 end print( tofunction(inhoge) ) return inhoge(x1+1,x1+2) end
function: 023D3998 function: 023D3998 function: 023D3998 function: 023D3998
全部同値が返ってきたので、function(関数)にはちゃんと使い回せるようにキャッシュみたいなのがあるようです。賢い。
えー同じになってるだけじゃ無いの〜と言うわけで100000ループテストで、関数を外に出した場合(読込時にコンパイルされる位置)と比較してもほぼ同値でしたので問題ないでしょう…。
これで安心して関数内関数をご使用ください。
ところでconsolas
win10になってからconsolasフォントは綺麗ですよね。VScodeでフォントとしての格を上げました。
そんなconsolasなんですが、多のエディタやHTMLで指定すると日本語フォントがイマイチ…VScodeのように綺麗に表示してくれません。(ものによってはおまえはプロポーショナルを強引に固定してるのかってぐらい文字が左右に寄っちゃったり…)
VScodeの設定では以下のような感じで日本語設定は有りません。
Consolas, 'Courier New', monospace
一応windows.FontLinkレジストリを見てみても、リンク定義はされていません。
YuGothicでもないような綺麗さですし…。
正解はメイリオでした。
あれ?でも自分はwin7からのアプグレ組だから良いけど、win10クリーンインストールだと無いんじゃ…。