プロフィール

長太郎

Author:長太郎
プログラマーやってます。

カレンダー
10 | 2017/11 | 12
- - - 1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 - -
月別アーカイブ
最近の記事
最近のコメント
最近のトラックバック
カテゴリー
ブログ内検索
RSSフィード
リンク
FC2カウンター
メールフォーム

名前:
メール:
件名:
本文:

小さな天気予報

-天気予報コム- -FC2-
QRコード
QRコード
スポンサーサイト
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。


スポンサー広告 | 【--------(--) --:--:--】 | Trackback(-) | Comments(-)
【プログラム】Lua lua_newstate()で指定したメモリアロケータの呼び出し
lua_newstate()で自前のメモリアロケーション関数を指定できるので、どのような呼び出しを行っているのか調べてみました。
使用したのは lua 5.1.4。

まず、検証用のC++実装です。

●alloc_test.cpp


//// Lua アロケータ呼び出し挙動を検証
//// by 長太郎 Jul.6 2008

#include <stdio.h> // printf()
#include <string.h> // memcpy()
#include <stdlib.h> // malloc(), free()

extern "C" {
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
}

// myLuaAlloc()呼び出しカウンタ
static int s_nAllocCallCount = 0;

//////// 自前アロケータ realloc()相当 ////////
static void *myLuaAlloc( void *ud, void *ptr, size_t osize, size_t nsize )
{
// Warning抑制
(void)ud; // 旧バッファ
(void)osize; // 旧サイズ

// 呼び出し情報表示
s_nAllocCallCount ++;
printf("%d : ud=%x ptr=%x osize=%d nsize=%d\n",
s_nAllocCallCount, ud, ptr, osize, nsize );

// 要求サイズが0なら開放する
if( nsize == 0 )
{
// 旧ポインタとサイズが0で呼ばれることが実際あるので
if( ptr )
{
free( ptr );
}
return 0;
}

//// 以下 realloc() と同じ挙動の実装 ////

// 新しいメモリを確保
void *pNewBuffer = malloc( nsize );

if( pNewBuffer == 0 )
{
// メモリ不足
return 0;
}

// 古いメモリの内容を新しいメモリにコピーする
if( ptr )
{
if( nsize >= osize )
{
memcpy( pNewBuffer, ptr, osize );
}
else
{
// このケースは必要なのかな?
memcpy( pNewBuffer, ptr, nsize );
}
// 古いメモリを開放
free( ptr );
}

return pNewBuffer;
}


//////// メイン ////////
int main()
{
// Lua環境準備
lua_State *L = lua_newstate( myLuaAlloc, NULL );

//// ここに色んなコードを入れて挙動を調査 ////

// 後始末
lua_close( L );

return 0;
}





検証用Luaスクリプトです。


●hello_world.lua


-- 簡単なスクリプト (lua-5.1.3)
print( "Hello world." )





●count_only.lua


-- 1から10までの合計を求めるだけ (lua-5.1.3)
total = 0;
for i = 1,10 do
total = total + i
end





●count_print.lua


--1から10までの合計を求めて表示(lua-5.1.3)
total = 0;
for i = 1,10 do
total = total + i
end
print( total )





alloc_test.cppの lua_newstate( ) と lua_close() の間に次のケース1~ケース5までのコードをいれ、何回 myLuaAlloc() が呼ばれているのか調べてみます。

●ケース1 何もしない
→ 102回
lua_newstate()直後にlua_close()をコールするだけで、myLuaAlloc()が102回コールされています。

出力はこんな感じです。


1 : ud=0 ptr=0 osize=0 nsize=376
2 : ud=0 ptr=0 osize=0 nsize=192
3 : ud=0 ptr=0 osize=0 nsize=720
4 : ud=0 ptr=0 osize=0 nsize=32
5 : ud=0 ptr=0 osize=0 nsize=0
6 : ud=0 ptr=0 osize=0 nsize=64
7 : ud=0 ptr=0 osize=0 nsize=32
8 : ud=0 ptr=0 osize=0 nsize=0
9 : ud=0 ptr=0 osize=0 nsize=64
10 : ud=0 ptr=0 osize=0 nsize=128
(・・・省略・・・)
95 : ud=0 ptr=70edd0 osize=19 nsize=0
96 : ud=0 ptr=70dd70 osize=22 nsize=0
97 : ud=0 ptr=6e45f0 osize=22 nsize=0
98 : ud=0 ptr=70ee10 osize=256 nsize=0
99 : ud=0 ptr=0 osize=0 nsize=0
100 : ud=0 ptr=6e14f8 osize=192 nsize=0
101 : ud=0 ptr=6e15e8 osize=720 nsize=0
102 : ud=0 ptr=6e1350 osize=376 nsize=0



ソースコードをみれば一目瞭然ですが、ptrは現在確保しているメモリのポインタ、 osizeは現在確保しているメモリサイズ、nsizeは要求メモリサイズです。
出力の1行目だと、 今はメモリ確保していないので新たに376 バイト割り当ててください、ということになります。
出力の102行目だと、今376バイト割り振られているけどもう使わないので開放してください、ということです。

nsizeが0のところは開放要求です。 102回のうち開放要求は54回ありました。
出力の5行目、8行目のように、意味もなくコールされている場合もあります。

ケース1ではリサイズ要求がありませんでしたが、他のケースではきちんとリサイズ要求がありました。

288 : ud=0 ptr=2985c0 osize=16 nsize=32
474 : ud=0 ptr=29b5f8 osize=32 nsize=53



●ケース2 標準関数を準備するだけ

luaL_openlibs( L );

→ 874回
一気に増えました。
準備する 関数の数が多いからこうなるのでしょう。

●ケース2 標準関数を準備して、printスクリプトを1回実行

luaL_openlibs( L );
luaL_dofile( L, "hello_world.lua" );

→ 912回
luaL_dofile()とスクリプト内のprint()1回コールで、38回 (=912-874) 増えています。

●ケース3 標準関数を準備して、printスクリプトを2回連続コール

luaL_openlibs( L );
luaL_dofile( L, "hello_world.lua" );
luaL_dofile( L, "hello_world.lua" );

→ 941回
1回のときより29回 (=941-912)増えました。


●ケース4 標準関数を準備して、1から10の合計を求める(結果は使用しない)

luaL_openlibs( L );
luaL_dofile( L, "count_only.lua" );

→ 934回
luaL_openlibs()だけ(=ケース2)より、60回(=934-874)増えました。

●ケース5 標準関数を準備して、1から10の合計を求めて結果をprint

luaL_openlibs( L );
luaL_dofile( L, "count_print.lua" );

→ 948回
print()1回のコールで14回 (=948-934) 増加。



想像していた以上に細々した呼び出しが多い、ということがわかりました。
いまどきのPCアプリを作成するには意識する必要は無いのかもしれませんが、私のやろうとしていた環境では無視することは出来なさそうです。
Luaを本格的に使うなら、こういった呼び出しを想定したアロケータを作らないと。
スポンサーサイト


プログラム | 【2008-07-06(Sun) 02:24:33】 | Trackback:(0) | Comments:(0)
コメントの投稿
管理者にだけ表示を許可する

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。