 Screenwriter, Choreographer, Game Developer

# Performance of Coral vs Vector3D and Matrix3D

Posted on

This is part 3 of a 4 part series comparing Coral, a derivative of the 3D math classes that used to be in the Flint Particles project, and Flash's native 3D math classes.

In the first post I introduced Coral, explaining what it is and why I'm releasing it as an open source project. The next post looked at the key architectural differences between Coral and the native Vector3D and Matrix3D classes. In a later post I will show you the bugs I discovered in the native 3D math classes. This post is about performance.

Coral is covered by a set of performance tests for measuring and optimizing it's performance. These tests are run using Grant Skinner's performance test suite. I adapted these tests to also apply to the native 3D geometry classes, for comparison. All the test code is in the Coral project on Github.

I ran these tests on my laptop, a MacBook with a 2.4GHz Core2Duo cpu, with the release version of Flash Player 10.2.152.26. All tests were over 1,000,000 iterations and each test is run four times and an average taken.

## Vector3d performance tests

 Coral Vector3d Performance tests. Native Vector3D Performance tests. Description Time (ms) Description Time (ms) % diff new Vector3d() 154.5 new Vector3D() 178 87% new Vector3d( x, y, z ) 156 new Vector3D( x, y, z ) 173.5 90% Vector3d.reset( x, y, z ) 21.75 v = new Vector3D( x, y, z ) 173.5 13% Vector3d.assign( v ) 17.25 u = v.clone() 183.75 9% Vector3d.clone() 179.75 Vector3D.clone() 183.75 98% Vector3d.add( v ) 171 Vector3D.add( v ) 183.25 93% Vector3d.add( v, r ) 13.5 Vector3D.add( v ) 183.25 7% Vector3d.subtract( v ) 176.25 Vector3D.subtract( v ) 184.25 96% Vector3d.subtract( v, r ) 13.75 Vector3D.subtract( v ) 184.25 7% Vector3d.multiply( s ) 205.5 Vector3D.clone().scaleBy( s ) 191.75 107% Vector3d.multiply( s, r ) 13 Vector3D.clone().scaleBy( s ) 191.75 7% Vector3d.divide( s ) 207 Vector3D.clone().scaleBy( 1 / s ) 199.75 104% Vector3d.divide( s, r ) 21.75 Vector3D.clone().scaleBy( 1 / s ) 199.75 11% Vector3d.incrementBy( v ) 11.75 Vector3D.incrementBy( v ) 11 107% Vector3d.decrementBy( v ) 12 Vector3D.decrementBy( v ) 12 100% Vector3d.scaleBy( s ) 9.75 Vector3D.scaleBy( s ) 10 98% Vector3d.divideBy( s ) 11 Vector3D.scaleBy( 1 / s ) 12.5 88% Vector3d.equals( v ) true 16.25 Vector3D.equals( v ) true 16.25 100% Vector3d.equals( v ) false 12.75 Vector3D.equals( v ) false 13.25 96% Vector3d.nearEquals( v ) true 13 Vector3D.nearEquals( v ) true 20 65% Vector3d.nearEquals( v ) false 13 Vector3D.nearEquals( v ) false 13.5 96% Vector3d.dotProduct( v ) 12.5 Vector3D.dotProduct( v ) 12 104% Vector3d.crossProduct( v ) 178 Vector3D.crossProduct( v ) 186.25 96% Vector3d.crossProduct( v, r ) 18.5 Vector3D.crossProduct( v ) 186.25 10% Vector3d.length 32.75 Vector3D.length 35.25 93% Vector3d.lengthSquared 9.25 Vector3D.lengthSquared 9 103% Vector3d.negative() 172 Vector3D.clone().negate() 192.75 89% Vector3d.negative( r ) 13.5 Vector3D.clone().negate() 192.75 7% Vector3d.negate() 10.75 Vector3D.negate() 11 98% Vector3d.normalize() 47 Vector3D.normalize() 45.75 103% Vector3d.unit() 222.75 Vector3D.clone().normalize() 240.75 93% Vector3d.unit( r ) 41.25 Vector3D.clone().normalize() 240.75 17%

Comparing Coral's Vector3d class to the native Vector3D class, the first thing I notice is that the majority of methods show insignificant differences. Those methods where significant differences occur are situations where Coral avoids creation of a temporary object. Thus, Coral is marginally faster when adding two vectors to produce a third new vector, but is very much quicker when it's allowed to use an existing vector to hold the result - something which the native vector class can't do.

## Point3d performance tests

 Coral Point3d Performance tests. Native Vector3D Performance tests. Description Time (ms) Description Time (ms) % diff new Point3d() 155 new Vector3D() 178 87% new Point3d( x, y, z ) 164 new Vector3D( x, y, z ) 173.5 95% Point3d.reset( x, y, z ) 20.75 v = new Vector3D( x, y, z ) 173.5 12% Point3d.assign( v ) 12.5 u = Vector3D.clone() 183.75 7% Point3d.clone() 166.75 Vector3D.clone() 183.75 91% Point3d.add( v ) 173.5 Vector3D.add( v ) 183.25 95% Point3d.add( v, r ) 13.25 Vector3D.add( v ) 183.25 7% Point3d.subtract( v ) 170.75 Vector3D.subtract( v ) 184.25 93% Point3d.subtract( v, r ) 14 Vector3D.subtract( v ) 184.25 8% Point3d.incrementBy( v ) 11.75 Vector3D.incrementBy( v ) 11 107% Point3d.decrementBy( v ) 10.75 Vector3D.decrementBy( v ) 12 90% Point3d.equals( v ) true 15.25 Vector3D.equals( v ) true 16.25 94% Point3d.equals( v ) false 12 Vector3D.equals( v ) false 13.25 91% Point3d.nearTo( p ) true 13.75 Vector3D.nearEquals( v ) true 20 69% Point3d.nearTo( p ) false 13.75 Vector3D.nearEquals( v ) false 13.5 102% Point3d.distance( v ) 37 Vector3D.subtract( v ).length 214.75 17% Point3d.distanceSquared( v ) 12 Vector3D.subtract( v ).lengthSquared 194.25 6% Point3d.project() 15.75 Vector3D.project() 16.25 97%

As with Coral's Vector3d class, the Point3d class has comparable (usually marginally faster) performance where functionality is identical, but is very much faster where it is able to avoid creating a temporary object.

## Matrix3d performance tests

 Coral Matrix3d Performance tests. Native Matrix3D Performance tests. Description Time (ms) Description Time (ms) % diff new Matrix3d() 185 new Matrix3D() 242.75 76% new Matrix3d( n11, n12, ... ) 212 new Matrix3D( v ) 255.5 83% Matrix3d.clone() 218.75 Matrix3D.clone() 637.75 34% Matrix3d.rawData 536.75 Matrix3D.rawData 312.5 172% Matrix3d.rawData = v 120.75 Matrix3D.rawData = v 54.5 222% Matrix3d.assign( m ) 16.75 m1.rawData = m2.rawData 729.25 2% Matrix3d.newScale( x, y, z ) 208.25 new Matrix3D().appendScale( x, y, z ) 314.5 66% Matrix3d.newTranslation( x, y, z ) 209.75 new Matrix3D().appendTranslation( x, y, z ) 253.75 83% Matrix3d.newRotation( angle, axis, point ) 387.25 new Matrix3D().appendRotation( angle, axis, point ) 502.5 77% Matrix3d.newBasisTransform( v1, v2, v3 ) 266.75 - - Matrix3d.append( m ) 68.5 Matrix3D.append( m ) 65.75 104% Matrix3d.appendScale( x, y, z ) 14.75 Matrix3D.appendScale( x, y, z ) 83.25 18% Matrix3d.appendTranslation( x, y, z ) 25.5 Matrix3D.appendTranslation( x, y, z ) 21.25 120% Matrix3d.appendRotation( angle, axis, point ) 263.25 Matrix3D.appendRotation( angle, axis, point ) 273.25 96% Matrix3d.appendBasisTransform( v1, v2, v3 ) 104.75 - - Matrix3d.prepend( m ) 76.5 Matrix3D.prepend( m ) 65.75 116% Matrix3d.prependScale( x, y, z ) 14.75 Matrix3D.prependScale( x, y, z ) 171.5 9% Matrix3d.prependTranslation( x, y, z ) 22.25 Matrix3D.prependTranslation( x, y, z ) 89.5 25% Matrix3d.prependRotation( angle, axis, point ) 278.25 Matrix3D.prependRotation( angle, axis, point ) 273.25 102% Matrix3d.prependBasisTransform( v1, v2, v3 ) 103.5 - - Matrix3d.determinant 30.75 Matrix3D.determinant 84 37% Matrix3d.invert() 138.5 Matrix3D.invert() 150.5 92% Matrix3d.inverse() 315.75 Matrix3D.clone().invert() 821.5 38% Matrix3d.inverse( r ) 127.75 Matrix3D.clone().invert() 821.5 16% Matrix3d.transformVector( v ) 187.75 Matrix3D.deltaTransformVector( v ) 542 35% Matrix3d.transformVector( v, r ) 23.75 Matrix3D.deltaTransformVector( v ) 542 4% Matrix3d.transformVectorSelf( v ) 19.5 Matrix3D.deltaTransformVector( v ) 542 4% Matrix3d.transformPoint( v ) 186.5 Matrix3D.transformVector( v ) 537.5 35% Matrix3d.transformPoint( v, r ) 23.5 Matrix3D.transformVector( v ) 537.5 4% Matrix3d.transformPointSelf( v ) 19.5 Matrix3D.transformVector( v ) 537.5 4% Matrix3d.transformVectors( v )* 903 - - Matrix3d.transformVectors( v, r )* 182 - - Matrix3d.transformVectorsSelf( v )* 184 - - Matrix3d.transformPoints( v )* 904.5 Matrix3D.transformVectors( v, r )* 129.75 697% Matrix3d.transformPoints( v, r )* 183 Matrix3D.transformVectors( v, r )* 129.75 141% Matrix3d.transformPointsSelf( v )* 184.5 Matrix3D.transformVectors( v, r )* 129.75 142%

* collection being transformed contained 30 vectors/points

The results of the matrix tests are more diverse than the vector and point tests. Creating transformation matrices using 'new' plus the various append/prepend transformation methods will usually be quicker with Coral than with the native classes. In some cases (e.g. prependScale) the difference is very large.

However, it could be argued that this is rarely important. The area where real speed is needed is when performing transformations on vectors and points. Here the performance profiles differ. Coral is very much faster when performing transformations on individual vectors and points, where it can produce a 25x speed improvement by avoiding creating temporary objects.

However, if you bundle all your points into a Vector.<Number> collection, the native Matrix3D class outperforms everything else.

## Next

That's all for performance. Overall I have found Coral to be a lot more performant than the native 3D math classes. In the final post in this series I will look at the bugs in Flash's native 3D classes that were revealed by applying Coral's unit tests to the native 3D classes.

## Footnote

The new Flash Player 11 Incubator pre-release became available on 28 February. This pre-release is only available as a debug version, so results from it are not comparable to the release players. Even so, I ran the tests out of interest and it looks like Matrix3D.transformVectors() has got a lot faster. There is nothing else of significance to draw from the debug version - we'll have to wait for a release version to land to find out more.