リスト(または文字列)操作のLSL2とMonoでの違いについてまとめています。
サーバーのバージョン1.25より以前のMonoでは使用メモリのカウントがあいまい[]
1.24までは、Monoコンパイルしたスクリプトが使用するメモリ量のカウントプログラムの処理が厳密ではなく、一時的に64KBをオーバーするような状況も許容していました。
1.25で導入された新しいスクリプト実行スケジューラでは、より厳密にスクリプトが使用しているメモリ量を監視するようになっています。
【参考】
- Babbage Linden Office Hour 2009/01/28
リスト要素追加時のハックはMonoでは無駄にメモリを消費します[]
LSL2でスクリプトが使用するメモリを節約する手法として、要素を追加する際に以下のように記述するハックがありました。
list_data = ( list_data = [] ) + list_data + new_item;
このように記述すると右辺の演算結果である新しいリストがスクリプトのメモリ領域にコピーされる前に、古いリストデータを空にでき、メモリを効率よく使用できていました。
しかしこの手法はMonoでは無効になっています。
この手法の動作をLSL2とMonoで比較したのが次の図です。
LSL2の場合[]
LSL2の場合はスクリプト用のメモリ領域とVM用のメモリ領域が独立しており、VM上でライブラリ関数の実行や演算が行わている間にスクリプト用の領域をクリアしておくというのがこの手法です。
Monoの場合[]
Monoの場合は、スクリプト用の領域内ですべての演算が行われます。したがって、リストに要素の追加を行う場合は、以下のように必ず元のリストとは別に新しく生成されたリストの分のメモリ領域が必要になります。(次節参照)
- 元のリストと追加する要素を足した新しいリストがヒープに生成される
- 生成されたヒープへのポインタが元の変数に設定される
したがって、上の図でMonoの場合は2と3が無駄な処理となり、また空のリスト変数分のメモリも無駄となります。
【参考】
- Babbage Linden Office Hour 2009/02/04
Monoでリスト変数コピー時のメモリ[]
上の図のMonoの場合の4で、元のリスト変数と追加する要素からなる新しいリストデータが生成されますが、このリストデータは、この時点ではディープコピーではなく、要素へのポインタ部分のみで新しいリストとして生成されます。
各要素の値のコピーが作成されるわけではないため、元の要素の2倍近くのメモリが必要ということはありません。
※LSL2の場合はディープコピーでした。
【参考】