Skip to content

Commit

Permalink
Reuse temp variables in Aabb2.transform methods. (#211)
Browse files Browse the repository at this point in the history
* Reuse temp variables in Aabb2.transform methods.
Improve consistency in avoiding public getters in a number of methods.
Add benchmarks for affected code to ensure positive performance impact.

Aabb2.transform is about 11% faster with these changes.
Aabb2.rotate is about 17% faster with these changes.

The rest of the changes had no measurable benchmark impact, but improve
consistency in the source base.

(Added .idea directory from IntelliJ/Android Studio to .gitignore)

* Update 64-bit sources to match.

* Ran dartfmt on files.

* Apply same optimization to Aabb3 methods.

Aabb3.transform is about 11% faster with the change.
Aabb3.rotate is about 14% faster with the change.
  • Loading branch information
flar authored and johnmccutchan committed Jul 26, 2019
1 parent 4b6d6a8 commit fdd8bf7
Show file tree
Hide file tree
Showing 8 changed files with 360 additions and 118 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -6,3 +6,4 @@ pubspec.lock
.pub
.packages
.dart_tool
.idea
229 changes: 229 additions & 0 deletions benchmark/matrix_bench.dart
Expand Up @@ -4,6 +4,7 @@

library vector_math_matrix_bench;

import 'dart:math' as math;
import 'dart:typed_data';
import 'package:vector_math/vector_math.dart';
import 'package:vector_math/vector_math_operations.dart';
Expand Down Expand Up @@ -101,10 +102,238 @@ class ViewMatrixBenchmark extends BenchmarkBase {
}
}

class Aabb2TransformBenchmark extends BenchmarkBase {
Aabb2TransformBenchmark() : super("aabb2Transform");

static final Matrix3 M = Matrix3.rotationZ(math.pi / 4);
static final Vector2 P1 = Vector2(10.0, 10.0);
static final Vector2 P2 = Vector2(20.0, 30.0);
static final Vector2 P3 = Vector2(100.0, 50.0);
static final Aabb2 B1 = Aabb2.minMax(P1, P2);
static final Aabb2 B2 = Aabb2.minMax(P1, P3);
static final Aabb2 B3 = Aabb2.minMax(P2, P3);
static final Aabb2 temp = Aabb2();

static void main() {
Aabb2TransformBenchmark().report();
}

@override
void run() {
for (int i = 0; i < 100; i++) {
temp.copyFrom(B1);
temp.transform(M);
temp.copyFrom(B2);
temp.transform(M);
temp.copyFrom(B3);
temp.transform(M);
}
}
}

class Aabb2RotateBenchmark extends BenchmarkBase {
Aabb2RotateBenchmark() : super("aabb2Rotate");

static final Matrix3 M = Matrix3.rotationZ(math.pi / 4);
static final Vector2 P1 = Vector2(10.0, 10.0);
static final Vector2 P2 = Vector2(20.0, 30.0);
static final Vector2 P3 = Vector2(100.0, 50.0);
static final Aabb2 B1 = Aabb2.minMax(P1, P2);
static final Aabb2 B2 = Aabb2.minMax(P1, P3);
static final Aabb2 B3 = Aabb2.minMax(P2, P3);
static final Aabb2 temp = Aabb2();

static void main() {
Aabb2RotateBenchmark().report();
}

@override
void run() {
for (int i = 0; i < 100; i++) {
temp.copyFrom(B1);
temp.rotate(M);
temp.copyFrom(B2);
temp.rotate(M);
temp.copyFrom(B3);
temp.rotate(M);
}
}
}

class Aabb3TransformBenchmark extends BenchmarkBase {
Aabb3TransformBenchmark() : super("aabb3Transform");

static final Matrix4 M = Matrix4.rotationZ(math.pi / 4);
static final Vector3 P1 = Vector3(10.0, 10.0, 0.0);
static final Vector3 P2 = Vector3(20.0, 30.0, 1.0);
static final Vector3 P3 = Vector3(100.0, 50.0, 10.0);
static final Aabb3 B1 = Aabb3.minMax(P1, P2);
static final Aabb3 B2 = Aabb3.minMax(P1, P3);
static final Aabb3 B3 = Aabb3.minMax(P2, P3);
static final Aabb3 temp = Aabb3();

static void main() {
Aabb3TransformBenchmark().report();
}

@override
void run() {
for (int i = 0; i < 100; i++) {
temp.copyFrom(B1);
temp.transform(M);
temp.copyFrom(B2);
temp.transform(M);
temp.copyFrom(B3);
temp.transform(M);
}
}
}

class Aabb3RotateBenchmark extends BenchmarkBase {
Aabb3RotateBenchmark() : super("aabb3Rotate");

static final Matrix4 M = Matrix4.rotationZ(math.pi / 4);
static final Vector3 P1 = Vector3(10.0, 10.0, 0.0);
static final Vector3 P2 = Vector3(20.0, 30.0, 1.0);
static final Vector3 P3 = Vector3(100.0, 50.0, 10.0);
static final Aabb3 B1 = Aabb3.minMax(P1, P2);
static final Aabb3 B2 = Aabb3.minMax(P1, P3);
static final Aabb3 B3 = Aabb3.minMax(P2, P3);
static final Aabb3 temp = Aabb3();

static void main() {
Aabb3RotateBenchmark().report();
}

@override
void run() {
for (int i = 0; i < 100; i++) {
temp.copyFrom(B1);
temp.rotate(M);
temp.copyFrom(B2);
temp.rotate(M);
temp.copyFrom(B3);
temp.rotate(M);
}
}
}

class Matrix3DeterminantBenchmark extends BenchmarkBase {
Matrix3DeterminantBenchmark() : super("Matrix3.determinant");

final Matrix3 MX = Matrix3.rotationX(math.pi / 4);
final Matrix3 MY = Matrix3.rotationY(math.pi / 4);
final Matrix3 MZ = Matrix3.rotationZ(math.pi / 4);

static void main() {
Matrix3DeterminantBenchmark().report();
}

@override
void run() {
for (int i = 0; i < 800; i++) {
MX.determinant();
MY.determinant();
MZ.determinant();
}
}
}

class Matrix3TransformVector3Benchmark extends BenchmarkBase {
Matrix3TransformVector3Benchmark() : super("Matrix3.transform(Vector3)");

final Matrix3 MX = Matrix3.rotationX(math.pi / 4);
final Matrix3 MY = Matrix3.rotationY(math.pi / 4);
final Matrix3 MZ = Matrix3.rotationZ(math.pi / 4);
final Vector3 V1 = Vector3(10.0, 20.0, 1.0);
final Vector3 V2 = Vector3(-10.0, 20.0, 1.0);
final Vector3 V3 = Vector3(10.0, -20.0, 1.0);

static void main() {
Matrix3TransformVector3Benchmark().report();
}

@override
void run() {
for (int i = 0; i < 800; i++) {
MX.transform(V1);
MX.transform(V2);
MX.transform(V3);
MY.transform(V1);
MY.transform(V2);
MY.transform(V3);
MZ.transform(V1);
MZ.transform(V2);
MZ.transform(V3);
}
}
}

class Matrix3TransformVector2Benchmark extends BenchmarkBase {
Matrix3TransformVector2Benchmark() : super("Matrix3.transform(Vector2)");

final Matrix3 MX = Matrix3.rotationX(math.pi / 4);
final Matrix3 MY = Matrix3.rotationY(math.pi / 4);
final Matrix3 MZ = Matrix3.rotationZ(math.pi / 4);
final Vector2 V1 = Vector2(10.0, 20.0);
final Vector2 V2 = Vector2(-10.0, 20.0);
final Vector2 V3 = Vector2(10.0, -20.0);

static void main() {
Matrix3TransformVector2Benchmark().report();
}

@override
void run() {
for (int i = 0; i < 800; i++) {
MX.transform2(V1);
MX.transform2(V2);
MX.transform2(V3);
MY.transform2(V1);
MY.transform2(V2);
MY.transform2(V3);
MZ.transform2(V1);
MZ.transform2(V2);
MZ.transform2(V3);
}
}
}

class Matrix3TransposeMultiplyBenchmark extends BenchmarkBase {
Matrix3TransposeMultiplyBenchmark() : super("Matrix3.transposeMultiply");

final Matrix3 MX = Matrix3.rotationX(math.pi / 4);
final Matrix3 MY = Matrix3.rotationY(math.pi / 4);
final Matrix3 MZ = Matrix3.rotationZ(math.pi / 4);
final Matrix3 temp = Matrix3.zero();

static void main() {
Matrix3TransposeMultiplyBenchmark().report();
}

@override
void run() {
for (int i = 0; i < 100; i++) {
temp.setIdentity();
temp.transposeMultiply(MX);
temp.transposeMultiply(MY);
temp.transposeMultiply(MZ);
}
}
}

void main() {
MatrixMultiplyBenchmark.main();
SIMDMatrixMultiplyBenchmark.main();
VectorTransformBenchmark.main();
SIMDVectorTransformBenchmark.main();
ViewMatrixBenchmark.main();
Aabb2TransformBenchmark.main();
Aabb2RotateBenchmark.main();
Aabb3TransformBenchmark.main();
Aabb3RotateBenchmark.main();
Matrix3DeterminantBenchmark.main();
Matrix3TransformVector3Benchmark.main();
Matrix3TransformVector2Benchmark.main();
Matrix3TransposeMultiplyBenchmark.main();
}
37 changes: 20 additions & 17 deletions lib/src/vector_math/aabb2.dart
Expand Up @@ -76,34 +76,37 @@ class Aabb2 {
_max.setFrom(other._max);
}

static Vector2 _center;
static Vector2 _halfExtents;
void _updateCenterAndHalfExtents() => copyCenterAndHalfExtents(
_center ??= Vector2.zero(),
_halfExtents ??= Vector2.zero(),
);

/// Transform this by the transform [t].
void transform(Matrix3 t) {
final Vector2 center = Vector2.zero();
final Vector2 halfExtents = Vector2.zero();
copyCenterAndHalfExtents(center, halfExtents);
_updateCenterAndHalfExtents();
t
..transform2(center)
..absoluteRotate2(halfExtents);
..transform2(_center)
..absoluteRotate2(_halfExtents);
_min
..setFrom(center)
..sub(halfExtents);
..setFrom(_center)
..sub(_halfExtents);
_max
..setFrom(center)
..add(halfExtents);
..setFrom(_center)
..add(_halfExtents);
}

/// Rotate this by the rotation matrix [t].
void rotate(Matrix3 t) {
final Vector2 center = Vector2.zero();
final Vector2 halfExtents = Vector2.zero();
copyCenterAndHalfExtents(center, halfExtents);
t.absoluteRotate2(halfExtents);
_updateCenterAndHalfExtents();
t.absoluteRotate2(_halfExtents);
_min
..setFrom(center)
..sub(halfExtents);
..setFrom(_center)
..sub(_halfExtents);
_max
..setFrom(center)
..add(halfExtents);
..setFrom(_center)
..add(_halfExtents);
}

/// Create a copy of this that is transformed by the transform [t] and store
Expand Down
37 changes: 20 additions & 17 deletions lib/src/vector_math/aabb3.dart
Expand Up @@ -203,34 +203,37 @@ class Aabb3 {
_max.setFrom(other._max);
}

static Vector3 _center;
static Vector3 _halfExtents;
void _updateCenterAndHalfExtents() => copyCenterAndHalfExtents(
_center ??= Vector3.zero(),
_halfExtents ??= Vector3.zero(),
);

/// Transform this by the transform [t].
void transform(Matrix4 t) {
final Vector3 center = Vector3.zero();
final Vector3 halfExtents = Vector3.zero();
copyCenterAndHalfExtents(center, halfExtents);
_updateCenterAndHalfExtents();
t
..transform3(center)
..absoluteRotate(halfExtents);
..transform3(_center)
..absoluteRotate(_halfExtents);
_min
..setFrom(center)
..sub(halfExtents);
..setFrom(_center)
..sub(_halfExtents);
_max
..setFrom(center)
..add(halfExtents);
..setFrom(_center)
..add(_halfExtents);
}

/// Rotate this by the rotation matrix [t].
void rotate(Matrix4 t) {
final Vector3 center = Vector3.zero();
final Vector3 halfExtents = Vector3.zero();
copyCenterAndHalfExtents(center, halfExtents);
t.absoluteRotate(halfExtents);
_updateCenterAndHalfExtents();
t.absoluteRotate(_halfExtents);
_min
..setFrom(center)
..sub(halfExtents);
..setFrom(_center)
..sub(_halfExtents);
_max
..setFrom(center)
..add(halfExtents);
..setFrom(_center)
..add(_halfExtents);
}

/// Create a copy of this that is transformed by the transform [t] and store
Expand Down

0 comments on commit fdd8bf7

Please sign in to comment.