スクリプトの高速化 その1

れむ

2008年04月02日 20:59


前回の関数の補足ついでにスクリプトの処理速度についてです。

こっちにあるmax()と
下記関数の実行時間を比較してみます。

float max(list lst)
{
    integer i;
    integer len = llGetListLength(lst);
    float m = llList2Float(lst, 0);
    float n;
    for (i = 1; i < len; i++) {
        n = llList2Float(lst, i);
        if (m < n) {
            m = n;
        }
    }
    return m;
}

どちらもリストに含む数値の最大値を求める関数です。
仮に前者をA、後者をBとしておきます。

Aはリストのデータを降順ソート(大きい順に並び替え)して先頭の値を返しています。
Bは単純に比較しているだけです。

想像してもわかる通り、一般的にソートは重い処理ですが、見かけ上は関数2個分です。

リストに渡すデータ数は400個のランダムデータです。
さて、どちらがどの程度速いでしょうか?

とまぁ、そんな問題を出すまでもなく
公開したAが速いのはバレバレなので、さっさと結果を見てみましょう。


結果
A …… 0.065191
B …… 7.144770

100倍以上の差が出ました。
まぁそういう訳です。

普通にスクリプトではないプログラミング言語で同じようなことをしたら、Bのような方法のほうが速くなります。
考えてみればわかるようにソートするにはBのような全検索処理も必要になるからです。

では、何故Aの方が速いかというと、それは行数が多いからです。
いい加減な理由かと思いますが、そうなのです。

LSLの仕様として組み込まれた処理は内部の最適化された処理として動作します。
一方、スクリプトとして書いたものはセカンドライフというアプリケーションの上で解析されながら動作します。

この差が非常に大きいのです。

既存の関数だけで同じようなことができるのであれば、アルゴリズムに関係なくその方が速くなるのです。

正直、ここまで差が出るとは思いませんでしたが。


ただ、今回のAには欠点があります。
それはリストの数を400という中途半端な数にしたことに答えがあります。

Aではこれ以上増やすとメモリが足りなくてソートができないからです。
(そんな個数を扱うことはそうそうないとは思いますが)


要するに地味な努力が速度UPに繋がったり、SIMの負荷を軽減したりする訳です。

実用上では本当に地味にしか変わりませんが、そんなことは言わないで下さい。(汗)
※ 細かい部分はわかり易いように省略していますので、ツッコミは控えめでお願いします。

また、その2の予定もネタもありません。
スクリプト