9

必要以上に遅いと思われる Lua プログラムを持っています。問題は、連想配列に値を1つずつ追加していて、テーブルが毎回新しいメモリを割り当てなければならないことだと思います。

table.setn 関数があったようですが、Lua 5.1.3 では失敗します。

stdin:1: 'setn' is obsolete
stack traceback:
        [C]: in function 'setn'
        stdin:1: in main chunk
        [C]: ?

私が行った Google 検索から、この機能は Lua 5.1 で廃止されたことがわかりましたが、機能を置き換えたもの (もしあれば) を見つけることができません。

Lua でテーブルのサイズを事前に設定する方法を知っていますか?

または、オブジェクトをテーブルに追加するときにメモリ割り当てを回避する他の方法はありますか?

4

6 に答える 6

11

あなたの質問にもっと集中させてください:

一度に 1 つずつ連想配列に値を追加する

Lua のテーブルは連想ですが、配列形式 (1..N) で使用すると最適化されます。彼らは内部的に二重の顔をしています。

だから..実際に連想的に値を追加している場合は、上記のルールに従ってください。

インデックス 1..N を使用している場合は、t[100000]= 何かを設定することで、1 回限りのサイズ再調整を強制できます。これは、Lua ソース内で指定された最適化された配列サイズの制限 (2^26 = 67108864) まで機能するはずです。その後、すべてが関連付けられます。

ps古い「setn」メソッドは配列部分のみを処理したため、連想使用には使用できません(これらの回答は無視してください)。

pps Lua のパフォーマンスを高く保つための一般的なヒントを調べましたか? つまり、テーブルの作成を知っており、新しいテーブルを作成するよりもむしろテーブルを再利用し、'local print=print' などを使用してグローバル アクセスを回避します。

于 2008-09-30T12:49:26.150 に答える
8
static int new_sized_table( lua_State *L )
{
    int asize = lua_tointeger( L, 1 );
    int hsize = lua_tointeger( L, 2 );
    lua_createtable( L, asize, hsize );
    return( 1 );
}

...

lua_pushcfunction( L, new_sized_table );
lua_setglobal( L, "sized_table" );

次に、ルアで、

array = function(size) return sized_table(size,0) end

a = array(10)

これを実行する簡単なハックとして、C を に追加できますlua.c

于 2008-09-28T22:28:38.490 に答える
5

私はあなたができるとは思いません-それは配列ではなく、perlハッシュやawk配列のような連想配列です。

http://www.lua.org/manual/5.1/manual.html#2.5.5

Lua側から意味のあるサイズをプリセットできるとは思いません。

ただし、C側にアレイを割り当てる場合は、

void lua_createtable (lua_State *L, int narr, int nrec);

あなたが必要なものかもしれません。

新しい空のテーブルを作成し、スタックにプッシュします。新しいテーブルには、narr配列要素とnrec非配列要素用に事前に割り当てられたスペースがあります。この事前割り当ては、テーブルに含まれる要素の数が正確にわかっている場合に役立ちます。それ以外の場合は、関数lua_newtableを使用できます。

于 2008-09-23T23:28:45.603 に答える
1

これは主な質問には答えませんが、2 番目の質問には答えます。

または、オブジェクトをテーブルに追加するときにメモリ割り当てを回避する他の方法はありますか?

カスタム アプリケーションで Lua を実行している場合は、C コーディングを行ってから推測できるように、アロケーターを Loki の小さな値のアロケーターに置き換えることをお勧めします。これにより、メモリ割り当てが 100 倍以上減少しました。これにより、カーネルへのラウンドトリップが回避されてパフォーマンスが向上し、プログラマとしての満足度が大幅に向上しました:)

とにかく、私は他のアロケーターを試しましたが、それらはより一般的であり、Lua アプリケーションに利益をもたらさない保証 (スレッドセーフ、大きなオブジェクトの割り当てなど) を提供します。また、独自の小さなオブジェクトのアロケーターを作成することもプログラミングとデバッグの良い週で、利用可能な解決策を探した後、Loki のアロケータは、この問題に対して私が見つけた中で最も簡単で最速でした。

于 2008-11-28T01:48:58.677 に答える
1

次のように、特定の量の項目を含むコードでテーブルを宣言する場合:

local tab = { 0, 1, 2, 3, 4, 5, ... , n }

次に、Lua は、少なくともnアイテムに割り当てられたメモリを使用してテーブルを作成します。

ただし、Lua は 2 倍のインクリメンタル メモリ割り当て手法を使用するため、テーブルに項目を追加しても再割り当てが強制されることはほとんどありません。

于 2009-09-28T15:39:02.003 に答える
1

内部 luaL_setn がまだあり、Lua をコンパイルして table.setn として公開できます。しかし、コードが事前拡張を行っていないように見えるため、役に立たないようです。

(setnの上にコメントされているsetnもLuaテーブルの配列部分に関連しており、テーブルを連想配列として使用しているとのことでした)

良い点は、要素を 1 つずつ追加しても、Lua はそのように配列を増加させないことです。代わりに、より合理的な戦略を使用します。より大きな配列に対して複数の割り当てを取得できますが、パフォーマンスは毎回新しい割り当てを取得するよりも優れています。

于 2008-09-24T07:29:41.143 に答える