myara CG blog

CG Design Blog. Thoughts, experiments and experiences.

VBS - JScript の For Loop Performance について

スクリプティングな話です。XSIとあんまり関係ないかもしれません。


baseで拾ったコードをどうやって速くなったかこれから少しだけ説明したいと思います。


まずは、XSI男を出して、コードをそのままでためしてみると:

54105 ミリ秒

使いたくないほどの遅さ。

コードを見てみると:

            if (angle >= hardEdgeLimit) then
               AddToSelection edgeName
            else
               RemoveFromSelection edgeName
            end if

エッジでループして、エッジを選択して、要らないエッジは RemoveFromSelection で選択削除されています。

通りで遅いじゃん!

これをコレクションに直してみて


set oCol = CreateObject("XSI.Collection" )
for each oEdge in oEdges
set oPolys = oEdge.NeighborPolygons
if (oPolys.Count = 2) then
dim angle, edgeName
angle = GetFacetAngle(oPolys(0), oPolys(1))
edgeName = oSelection.FullName & "." & oEdge.FullName & "[" & oEdge.Index & "]"
if (angle >= hardEdgeLimit) then
oCol.AddItems (edgeName)
end if
end if
next
selectObj(oCol)


ログをオフにして、


'Log Off
set oCmdLog = Dictionary.GetObject( "preferences.scripting" )
userPref = oCmdLog.cmdlog.value
oCmdLog.cmdlog.value = false


無駄なところを削除してみると:

24832 ミリ秒

2倍以上速くなった!


と考えると上出来だけど、24秒以上じゃあ遅いよね・・・。
こんなローポリのXSI男なのに。


でもしょうがない、とりあえずそのままJScriptに変えてみます。
PPGが欲しいし、VBSでプラグインを書く気にならない。


ついでに、この古い書き方
CreateObject("Sumatra\Scripting\Math\SIVector3")

を新しいXSIMath
XSIMath.CreateVector3()

に変える、10ミリ秒ぐらい速くなる気がします。

あとは、色々好きにアレンジして、PPGを付けてみました。

試してみたら・・・

JScript
998 ミリ秒

速い!なんだこの差!

期待以上の速さです。

なんでVBSの方がそんなに遅いのか・・・ちょっと考えてたら

まさかアレですか。
れいのアレですか!

あのDIMってやつ?

それしか思い浮かばないけど、こんな差はいくらなんでも大きすぎでしょう。

試してみます。

VBSコードをOption Implicit にして、変数を全部宣言して、あっちこっち修正してためしてみたら・・・

652 ミリ秒

速っ!

変数を宣言しただけでめちゃめちゃ速くなりますね。
宣言するとすぐどの変数かコードがすぐ分かるから速いですが、宣言しないとどこの変数か分からないから探し続けるからだそうです。

因みに、プロパティとかより、変数の方が速いです。
要するに、コードでオブジェクトのプロパティを何回も取得することより、
一回だけで取得して変数の値に変えておくと、
あとはその変数を呼ぶだけでいいから速いです。

まぁ、変数とかのことはこのブログじゃなくて、ちゃんとしたサイトで調べた方が良いかもしれなですw


しかし、なんで!?

なんでJScriptより速い?!

コードは一緒ですよ。

違いはループだけですね。
JScriptでは for ループを使っていて、VBSの方はfor each ループでやっています。
JScript には for eachがないからね、そして、for in はなぜか、XSIコレクションには使えません。

試しに VBSでも for ループでやってみたら:

793 ミリ秒

えっ、VBS の for ループは遅いんだ!

ていうか for each が速いかな。

速くなったのは嬉しいんだけど、PPG付きのJScriptより速くなるのは悔しい。
なので、JScriptの方も頑張ってみました。

速くはなったけど、VBSに負けてます:

JScript
810 ミリ秒


ポイントはfor ループです。

for (var i=0; i<Collection.count; i++)




for (var i=0, a = Collection.count; i<a; i++)


に変えるだけで100ms以上速くなりました。

これは、上にも書いたけど、変数を作っておくと速いです。

i< Collection.count とは、ループが一周した後に、コレクションの数を取得して、i の数値と比べるということです。
コレクションの数と比べているから、毎回コレクションの数を取得するということになります。

コレクションの数を変数にすると、毎回この変数の数値を使って確認するだけなので速いです。

これからもこのやり方で書きます!