FANDOM


Scripters_cafeログ


08/09/27 編集

LSL2では、使わなくなった変数のヒープ領域の解放は同期的に行われていました。 従って、領域の確保・解放に対して非同期な要素を排除すると、スクリプトの処理を継続していった場合に空き領域がそのうちなくなるのか、なくならないのかは理論上計算可能でした。

Monoの実行環境の場合、使用しなくなった領域の解放はガベージコレクションによって自動的・非同期的に行われます。

現在ガベージコレクションがどういったタイミングで行われているのか不明なため、予期せずstack-heap collisionが発生してしまうケースがあるようです。


Fakeさんのテストコードを少し訂正した以下のテストコードでガベージコレクションの挙動を確認できます。

default {
    touch_start( integer total_number ) {
        integer i;
        list test;
        for ( i = 0; i < 1000; ++i ) {
            test += NULL_KEY;    
        }
        
        i = 0;
        while( TRUE ) {
            llSetText( (string)(++i), <1.0, 1.0, 1.0>, 1.0 );  // (1)
            test = llListReplaceList( test, [ NULL_KEY ], 0, 0 );  // (2)
        }
    }
}

このコードをMonoコンパイルしてプリムにタッチすると、なぜか(2)の箇所でstack-heap collisionが発生します。 しかも、一度stack-heap collisionが発生した後にスクリプトをリセットしてプリムにタッチ、というのを繰り返すと、(1)で表示される数字が変動します。


※(2)の処理では、リストの要素数を変更せずに先頭要素を入れ替えて、同じ変数に書き戻しているだけです。


この挙動から分かることは、

  • 関数の戻り値は以前と同じように一旦ヒープ領域に確保されている。
  • 戻り値が元の変数に置き換えられた後、元の変数が使用していた領域が解放されるはずだが、解放が同期的には行われていない。
    • 同期的に行われているならば、理論上メモリ使用量の増加は関数の戻り値の領域分のみなのでstack-heap collisionが発生するはずがない
  • stack-heap collisionが発生するタイミングが一定ではないので、ガベージコレクションのタイミングはスクリプトのコードに非依存で行われている。


実際のスクリプトで、このような状況でstack-heap collisionが発生してしまうのは非常に厄介です。 いくら使用できる容量が16kから64kに拡張されたといっても、未使用領域が即座に解放されないのでは意味がありません。


この点、Babbage Lindenのオフィスアワーにて質問してみたいと思います。


LSL2では 編集

上記のテストコードをLSL2で実行すると、初めのリスト確保の時点でstack-heap collisionが発生します。 要素数を300件程度にして、要素追加のvoodooを使用すれば、要素の確保は成功します。

Monoの場合はvoodooを使わずに1000件の確保ができますから、要素の追加操作に関してはMonoの場合メモリを効率的に使用するようになっていると思われます。


また、後半のllListReplaceListの部分ですが、LSL2の場合、関数呼び出しのパラメータ部にもvoodooを使用することで、関数呼び出し前に元の変数の領域を解放できます。 こうすると、stack-heap collisionを起こすことなく、処理が継続されます。



このページのTinyURL:http://tinyurl.com/SC-Mono-GC

広告ブロッカーが検出されました。


広告収入で運営されている無料サイトWikiaでは、このたび広告ブロッカーをご利用の方向けの変更が加わりました。

広告ブロッカーが改変されている場合、Wikiaにアクセスしていただくことができなくなっています。カスタム広告ブロッカーを解除してご利用ください。

FANDOMでも見てみる

おまかせWiki