Pointクラスと同機能自作クラスの速度比較。


Pointクラスの処理速度がどうも遅い。どれくらい遅いんだっけ、ってことで速度比較。

Pointクラスと同機能自作クラスの速度比較。 – wonderfl build flash online

たしかにPointクラスは遅い。計算だけなら、こんなクラス使わずに同内容の処理を書いちゃったほうが処理速度は5倍以上速い。だけど、だからと言って、この処理がボトルネックになることはあまり無いので、まずはPointクラスをどんどん利用してキレイにコードを組んで、一通りできてから最適化していったほうが開発はスムーズに進むと思う。
あまりに神経質に速度を求め、見渡しにくくしてしまうのはるのは、早すぎる最適化は諸悪の根源ってやつだ(自戒を込めて)。
[sourcecode language=”as3″]
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Point;
import flash.text.TextField;

/**
* Pointクラスと同機能自作クラスの速度比較。
* …
* @author umhr
*/
public class Main extends Sprite
{

public function Main()
{
init();
}
private function init():void
{
if (stage) onInit();
else addEventListener(Event.ADDED_TO_STAGE, onInit);
}

private function onInit(event:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, onInit);
// entry point

//var point:Point = new Point(3, 5);
//trace(point);
//trace(point.add(new Point(2, 4)));
//trace(point.subtract(new Point(4, 6)));
//point.normalize(3)
//trace(point);
//
//var pt:Pt = new Pt(3, 5);
//trace(pt);
//trace(pt.add(new Pt(2, 4)));
//trace(pt.subtract(new Pt(4, 6)));
//pt.normalize(3)
//trace(pt);

var textField:TextField = new TextField();
textField.width = 465;
textField.height = 465;
addChild(textField);

var text:String = "";

text += "対照用:" + test() + "\n";
text += "Pointクラスを用いて計算:" + pointTest() + "\n";
text += "自作の同機能Ptクラスを用いて計算:" + ptTest() + "\n";
text += "自作の同機能クラス化せずに計算:" + pTest() + "\n";

textField.text = text;

//new PtExample();
}
/**
* Pointクラスを用いて計算
* @return
*/
private function pointTest():Number {
var time:Number = new Date().time;
for (var i:int = 0; i < 1000000; i++)
{
var point:Point = new Point(Math.random(), Math.random());
point.add(new Point(Math.random(), Math.random()));
point.subtract(new Point(Math.random(), Math.random()));
point.normalize(3);

}
return new Date().time – time;
}
/**
* 自作の同機能Ptクラスを用いて計算
* @return
*/
private function ptTest():Number {
var time:Number = new Date().time;
for (var i:int = 0; i < 1000000; i++)
{
var point:Pt = new Pt(Math.random(), Math.random());
point.add(new Pt(Math.random(), Math.random()));
point.subtract(new Pt(Math.random(), Math.random()));
point.normalize(3);

}
return new Date().time – time;
}
/**
* 自作の同機能クラス化せずに計算
* @return
*/
private function pTest():Number {
var time:Number = new Date().time;
for (var i:int = 0; i < 1000000; i++)
{
var ax:Number = Math.random();
var ay:Number = Math.random();
var bx:Number = ax + Math.random();
var by:Number = ay + Math.random();
var cx:Number = ax – Math.random();
var cy:Number = ay – Math.random();

var thickness:Number = 3;
thickness /= Math.sqrt(ax * ax + ay * ay);
ax *= thickness;
ay *= thickness;

}
return new Date().time – time;
}
/**
* 対照用
* @return
*/
private function test():Number {
var time:Number = new Date().time;
for (var i:int = 0; i < 1000000; i++)
{

}
return new Date().time – time;
}

}

}

class Pt {
/**
* ポイントの水平座標です。
*/
public var x:Number;
/**
* ポイントの垂直座標です。
*/
public var y:Number;
/**
* 新しいポイントを作成します。
* @param x
* @param y
*/
public function Pt(x:Number = 0, y:Number = 0) {
this.x = x;
this.y = y;
};
/**
* このポイントの座標に他のポイントの座標を加算して、新しいポイントを作成します。
* @param pt
* @return
*/
public function add(pt:Pt):Pt {
return new Pt(pt.x + x, pt.y + y);
}
/**
* この Point オブジェクトのコピーを作成します。
* @return
*/
public function clone():Pt {
return new Pt(x, y);
}
/**
* [静的] pt1 と pt2 との距離を返します。
* @param pt1
* @param pt2
* @return
*/
public static function distance(pt1:Pt, pt2:Pt):Number {
var ptx:Number = pt1.x – pt2.x;
var pty:Number = pt1.y – pt2.y;
return Math.sqrt(ptx * ptx + pty * pty);
}
/**
* 2 つのポイントが等しいかどうかを判別します。
* @param toCompare
* @return
*/
public function equals(toCompare:Pt):Boolean {
return x == toCompare.x && y == toCompare.y;
}
/**
* [静的] 2 つの指定されたポイント間にあるポイントを判別します。
* @param pt1
* @param pt2
* @param f
* @return
*/
public static function interpolate(pt1:Pt, pt2:Pt, f:Number):Pt {
return new Pt(pt1.x + (pt2.x – pt1.x) * f, pt1.y + (pt2.y – pt1.y) * f);
}
/**
* [読み取り専用] (0,0) からこのポイントまでの線のセグメントの長さです。
*/
public function get length():Number {
return Math.sqrt(x * x + y * y);
}
/**
* (0,0) と現在のポイント間の線のセグメントを設定された長さに拡大 / 縮小します。
* @param thickness
*/
public function normalize(thickness:Number):void {
thickness /= Math.sqrt(x * x + y * y);
x *= thickness;
y *= thickness;
}
/**
* Point オブジェクトを指定された量だけオフセットします。
* @param dx
* @param dy
*/
public function offset(dx:Number, dy:Number):void {
x -= dx;
y -= dy;
}
/**
* [静的] 極座標ペアを直交点座標に変換します。
* @param len
* @param angle
* @return
*/
public static function polar(len:Number, angle:Number):Pt {
return new Pt(Math.cos(angle) * len, Math.sin(angle) * len);
}
/**
* このポイントの座標から他のポイントの座標を減算して、新しいポイントを作成します。
* @param pt
* @return
*/
public function subtract(pt:Pt):Pt {
return new Pt(x – pt.x, y – pt.y);
}
/**
* x 座標の値と y 座標の値を格納するストリングを返します。
* @return
*/
public function toString():String {
return "(x=" + x + ", y=" + y + ")";
}
}
/**
* Pointクラスの使用例より
* http://help.adobe.com/ja_JP/FlashPlatform/reference/actionscript/3/flash/geom/Point.html#includeExamplesSummary
*/
class PtExample{
public function PtExample() {
var point1:Pt = new Pt();
trace(point1); // (x=0, y=0)

var point2:Pt = new Pt(6, 8);
trace(point2); // (x=6, y=8)

trace(Pt.interpolate(point1, point2, 0.5)); // (x=3, y=4)

trace(Pt.distance(point1, point2)); // 10

trace(point1.add(point2)); // (x=6, y=8)

var point3:Pt = point2.clone();
trace(point2.equals(point3)); // true

point3.normalize(2.5);
trace(point3); // (x=1.5, y=2)

trace(point2.subtract(point3)); // (x=4.5, y=6)

trace(point1.offset(2, 3)); //

var angle:Number = Math.PI * 2 * (30 / 360); // 30 degrees
trace(Pt.polar(4, angle)) // (x=3.464101615137755, y=1.9999999999999998)
}
}
[/sourcecode]