| INDEX |

frocessingでは、Matrixを拡張してFMatrix2Dというクラスをつくっているのですが、その過程でどうもオリジナルの matrix.scale() と Matrix.rotate() が遅いんじゃないかと思いまして、以下試してみたものです。

とりあえずテスト用につくったもので、オリジナル(ori)と scale,translate,rotateをoverrideして実装しなおしたもの(ext)を、それぞれfor文でまわしたものです。影響が出そうな、createBox, createGradientBox についても比較しています。それぞれ10万回実行しています。

自分の環境では、translateは大体同じだけど、scale と rotate 及び影響が出ていると思われる box系で随分処理時間に差が出ています。どうでしょうか?

実際には10万回なんて実行しないので、現実的には差がないように思えますが、とりあえずメモということで。

以下実装し直した TestMatrix と 上のテストで使用したスクリプトです。

TestMatrix.as

package{
  
  import flash.geom.Matrix;
  
  public class TestMatrix extends Matrix
  {
    
    public function TestMatrix( a_:Number=1, b_:Number=0, c_:Number=0, d_:Number=1, tx_:Number=0, ty_:Number=0)
    {
      super( a_, b_, c_, d_, tx_, ty_ );
    }
    
    override public function translate( dx:Number, dy:Number ):void
    {
      //(1,0,0,1,dx,dy)
      tx += dx;
      ty += dy;
    }
    
    override public function scale( sx:Number, sy:Number ):void
    {
      //(sx,0,0,sx,0,0)
      a  *= sx;
      b  *= sy;
      c  *= sx;
      d  *= sy;
      tx *= sx;
      ty *= sy;
    }
    
    override public function rotate( angle:Number ):void
    {
      //(c, s, -s, c, 0, 0)
      var sin:Number = Math.sin(angle);
      var cos:Number = Math.cos(angle);
      var n11:Number = a * cos - b * sin;
      var n12:Number = a * sin + b * cos;
      var n21:Number = c * cos - d * sin; 
      var n22:Number = c * sin + d * cos;
      var n31:Number = tx * cos - ty * sin; 
      var n32:Number = tx * sin + ty * cos;
      a  = n11; b  = n12;
      c  = n21; d  = n22;
      tx = n31; ty = n32;
    }
  }
}

テストコード

//ベタなテストですいません
//out_txtはTextFieldです

var n:int = 50000;
var t:int;
var i:int;

var fmt:TestMatrix = new TestMatrix( 1, 2, 3, 4, 5, 6 );
var mt:Matrix = new Matrix( 1, 2, 3, 4, 5, 6 );

//---------------------------------------------
out_txt.appendText( "[SCALE]");

t = getTimer();
for( i=0; i<n; i++ )
{
mt.scale( 10, 10 ); mt.scale( 0.1,0.1 );
}
out_txt.appendText( "\n ori: " + (getTimer()-t).toString() );

t = getTimer();
for( i=0; i<n; i++ )
{
fmt.scale(10,10); fmt.scale(0.1,0.1);
}
out_txt.appendText( " ext: " + (getTimer()-t).toString() );

//---------------------------------------------
out_txt.appendText( "\n[TRANSLATE]");
t = getTimer();
for( i=0; i<n; i++ )
{
mt.translate( 10, 10 ); mt.translate( -10,-10 );
}
out_txt.appendText( "\n ori: " + (getTimer()-t).toString() );

t = getTimer();
for( i=0; i<n; i++ )
{
fmt.translate(10,10); fmt.translate(-10,-10);
}
out_txt.appendText( " ext: " + (getTimer()-t).toString() );

//---------------------------------------------
out_txt.appendText( "\n[ROTATE]");
t = getTimer();
for( i=0; i<n; i++ )
{
mt.rotate( 1.5 ); mt.rotate( -1.5 );
}
out_txt.appendText( "\n ori: " + (getTimer()-t).toString() );

t = getTimer();
for( i=0; i<n; i++ )
{
fmt.rotate(1.5); fmt.rotate(-1.5);
}
out_txt.appendText( " ext: " + (getTimer()-t).toString() );

//---------------------------------------------
out_txt.appendText( "\n[CREATE_BOX]");
t = getTimer();
for( i=0; i<n; i++ )
{
mt.createBox( 10, 10, 1, 1, 1 );
mt.createBox( 0.1, 0.1, -1, -1, -1 );
}
out_txt.appendText( "\n ori: " + (getTimer()-t).toString() );

t = getTimer();
for( i=0; i<n; i++ )
{
fmt.createBox( 10, 10, 1, 1, 1 );
fmt.createBox( 0.1, 0.1, -1, -1, -1 );
}
out_txt.appendText( " ext: " + (getTimer()-t).toString() );

//---------------------------------------------
out_txt.appendText( "\n[CREATE_GRADIENT_BOX]");
t = getTimer();
for( i=0; i<n; i++ )
{
mt.createGradientBox( 10, 10, 1, 1, 1 );
mt.createGradientBox( 0.1, 0.1, -1, -1, -1 );
}
out_txt.appendText( "\n ori: " + (getTimer()-t).toString() );

t = getTimer();
for( i=0; i<n; i++ )
{
fmt.createGradientBox( 10, 10, 1, 1, 1 );
fmt.createGradientBox( 0.1, 0.1, -1, -1, -1 );
}
out_txt.appendText( " ext: " + (getTimer()-t).toString() );

テストの方法が微妙な気がしますが、いいベンチマークの方法があったら知りたい…

| INDEX |