プロフィール

長太郎

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)
【プログラム】C++からLuaスクリプトを呼ぶテスト
C++で作成したプロジェクトに、Luaを組み込むテストをしてみました。

最初は「Hello world.」と表示するだけのスクリプトを書いて実行したけど、うまく表示されず。
原因を調べてみると、Lua標準print()を使うための準備をしていなかったからでした。

下記はうまく動いたコード。



●hello_world.lua

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




●simple00.cpp

// Luaスクリプトを実行する

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

int main()
{
// Lua環境準備
// lua_open()と同じ
// アロケーターを指定する場合はlua_newstate()を使う
lua_State *L = luaL_newstate();

// Lua標準のprint()などを使えるようにする
luaL_openlibs( L );

// Luaスクリプト読み込みと実行
luaL_dofile( L, "hello_world.lua" );

// 後始末
lua_close( L );

return 0;
}




プログラム | 【2008-07-05(Sat) 18:33:26】 | Trackback:(0) | Comments:(0)
【プログラム】C#でブラウザアプリのテスト
インストールしたまま使ってなかった「Visual Studio 2008 Express Editions」を立ち上げてみました。

C#と.NET Framework で何ができるかな?って感じでとりあえずプロジェクトを作成して画面を眺めていると、ツールボックスのコモンコントロールに「WebBrowser」というものを見つけたので使ってみることにしました。

適当にテキストボックスやボタンを配置して、1行だけコードを追加(太文字のところ)。

namespace Test00
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void button1_Click(object sender, EventArgs e)
{
webBrowser1.Navigate( textBox1.Text );
}
}
}




実行結果はこんな感じ。

C#ブラウザテスト


恐ろしく簡単です。

プログラム | 【2008-05-24(Sat) 19:58:04】 | Trackback:(0) | Comments:(0)
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。