Skip to content

Commit

Permalink
Merge 95cd895 into f4bc78b
Browse files Browse the repository at this point in the history
  • Loading branch information
ibgreen committed May 28, 2019
2 parents f4bc78b + 95cd895 commit 147b260
Show file tree
Hide file tree
Showing 22 changed files with 1,415 additions and 1,301 deletions.
72 changes: 72 additions & 0 deletions babel.config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,75 @@
// COPIED FROM ocular-dev-tools

const TARGETS = {
chrome: '60',
edge: '15',
firefox: '53',
ios: '10.3',
safari: '10.1',
node: '8'
};

const COMMON_CONFIG = {
comments: false
};

const ENV_CONFIG = {
es5: {
presets: [
[
'@babel/env',
{
forceAllTransforms: true,
modules: 'commonjs'
}
]
],
plugins: ['@babel/transform-runtime', ['transform-builtin-extend', {globals: ['Array']}]]
},
esm: {
presets: [
[
'@babel/env',
{
forceAllTransforms: true,
modules: false
}
]
],
plugins: [
['@babel/transform-runtime', {useESModules: true}],
['transform-builtin-extend', {globals: ['Array']}]
]
},
es6: {
presets: [
[
'@babel/env',
{
targets: TARGETS,
modules: false
}
]
],
plugins: [['@babel/transform-runtime', {useESModules: true}]]
},
test: {
presets: ['@babel/preset-env'],
plugins: ['istanbul']
}
};

// Ensure we have an entry for the default BABEL_ENV
ENV_CONFIG.development = ENV_CONFIG.es6;

module.exports = api => {
api.cache.using(() => process.env.BABEL_ENV);

return Object.assign({}, COMMON_CONFIG, ENV_CONFIG[api.env()]);
};

// END COPY

const getBabelConfig = require('ocular-dev-tools/config/babel.config');

module.exports = api => {
Expand Down
46 changes: 40 additions & 6 deletions docs/developer-guide/performance.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,39 @@ configure({debug: false});

## Minimizing Object Creation

One of the most typical performance issue in math.gl (including most other JavaScript math libraries) is object creation. Creating new `Vector` and `Matrix` instances has significant overhead. Therefore, reusing objects where possible is an important technique to optimize performance.
One of the most typical performance issue in math.gl (and most other JavaScript math libraries) is excessive object creation. Creating new `Vector` and `Matrix` instances every time a calculation is made incurs significant overhead. Therefore, reusing objects where possible is an important technique to optimize performance.

```js
for (...) {
const v = new Vector3(...);
const v = new Vector3(x, y, z);
}
```
vs.
```

```js
const tempVector = new Vector3();
for (...) {
v.set(...);
v.set(x, y, z);
}
```

Note that some methods, like `Matrix4.transformVector`, allocate new objects as return values. By providing an optional `target` argument you can prevent this allocation and reuse an object you have already allocated. This technique is borrowed the THREE.js math library where it is a commonly availble optimization.
Note that a number of methods, such as `Matrix4.transformVector()`, allocate new objects as return values. These methods typically accept an optional `result` argument which can be populated and returned. By providing a `result` value, you revent the allocation of a new object and instead reuse an object you have already allocated.

```js
for (...) {
const v = matrix4.transformVector([x, y, z]);
// v now contains a reference to a newly allocated `Vector3` which was updated with the result of the `tranformVector` operation.
}
```
vs.

```js
const tempVector = new Vector3();
for (...) {
const v = matrix4.transformVector([x, y, z], tempVector);
// v now contains a reference to `tempVector` which was updated with the result of the `tranformVector` operation.
}
```

## Browser, OS version etc

Expand All @@ -45,4 +61,22 @@ The JavaScript engine powering Chrome and Node is still improving. The performan

## Benchmarking

The math.gl repository comes with a benchmark suite that you can run in your environment to see what operations peform well and shich do not.
The math.gl repository comes with a benchmark suite that you can run to see what operations are fast and which take more time in your environment.

You can run the benchmarks both in Node.js and in the browser

```bash
yarn bench
yarn bench browser
```


## JavaScript Engine Optimizations

> This section should be considered advanced, and is not required reading for the normal math.gl user. However if you are writing your own math code it can be useful to have an understanding.
To get good performance it is important to structure code so that it can be compiled and optimized by the JavaScript engine in use. math.gl focuses on optimizing for the V8 engine, since it is used both by Chrome and Node.js, however the optimizations are general and should also be relevant to other optimizing JavaScript engines.

In particular, math.gl makes efforts to ensure that the engine knows that fields in math classes contain numbers, which allows for important optimizations that can result in a \~5x performance difference for simple operations.

A good introduction to the topic can be found in [JavaScript Performance Pitfalls in V8](https://ponyfoo.com/articles/javascript-performance-pitfalls-v8).
17 changes: 14 additions & 3 deletions docs/table-of-contents.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,19 @@
"title": "Developer Guide",
"entries": [
{"entry": "docs/developer-guide/get-started"},
{"entry": "docs/developer-guide/coordinate-systems"},
{"entry": "docs/developer-guide/debugging"},
{"entry": "docs/developer-guide/floating-point"},
{"entry": "docs/developer-guide/homogenous-coordinates"},
{"entry": "docs/developer-guide/performance"},
{"entry": "docs/developer-guide/rotations"},
{"entry": "docs/developer-guide/using-transformations"},
{"entry": "docs/developer-guide/view-and-projection"},
{"entry": "docs/developer-guide/coordinate-systems"},
{"entry": "docs/wip/features"},
{"entry": "docs/wip/using-vectors"},
{"entry": "docs/developer-guide/geospatial"},
{"entry": "docs/developer-guide/using-with-gl-matrix"},
{"entry": "docs/developer-guide/using-with-three-js"}
{"entry": "docs/developer-guide/concepts/homogenous-coordinates"},
{"entry": "docs/developer-guide/concepts/rotations"},
]
},
{
Expand Down Expand Up @@ -54,6 +55,16 @@
"entries": [
{"entry": "docs/api-reference/addons/polygon"}
]
},
{
"title": "Geospatial",
"entries": [
{"entry": "docs/api-reference/math/geospatial/README"},
{"entry": "docs/api-reference/math/geospatial/ellipsoid"}
{"entry": "docs/api-reference/math/geospatial/cartographic-rectangle"}
{"entry": "docs/api-reference/math/geospatial/geographic-projection"}
{"entry": "docs/api-reference/math/geospatial/web-mercator-projection"}
]
}
]
}
Expand Down
3 changes: 2 additions & 1 deletion modules/core/src/classes/euler.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
// THE SOFTWARE.

import MathArray from '../lib/math-array';
import {checkNumber, clamp} from '../lib/common';
import {clamp} from '../lib/common';
import {checkNumber} from '../lib/validators';
import Matrix4 from './matrix4';
import Quaternion from './quaternion';
import Vector3 from './vector3';
Expand Down
4 changes: 2 additions & 2 deletions modules/core/src/classes/matrix3.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

import Matrix from '../lib/matrix';
import {validateVector} from '../lib/validators';
// import {checkNumber} from '../lib/common';
// import {checkNumber} from '../lib/validators';
import Vector2 from './vector2';
import Vector3 from './vector3';

Expand Down Expand Up @@ -60,7 +60,7 @@ export default class Matrix3 extends Matrix {
}

constructor(...args) {
super(9);
super(-0, -0, -0, -0, -0, -0, -0, -0, -0);
if (Array.isArray(args[0]) && arguments.length === 1) {
this.copy(args[0]);
} else {
Expand Down
4 changes: 2 additions & 2 deletions modules/core/src/classes/matrix4.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
// THE SOFTWARE.

import Matrix from '../lib/matrix';
// import {checkNumber} from '../lib/common';
import {validateVector} from '../lib/validators';
// import {checkNumber} from '../lib/validators';
import Vector2 from './vector2';
import Vector3 from './vector3';
import Vector4 from './vector4';
Expand Down Expand Up @@ -69,7 +69,7 @@ export default class Matrix4 extends Matrix {
}

constructor(...args) {
super(16);
super(-0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0);
if (Array.isArray(args[0]) && arguments.length === 1) {
this.copy(args[0]);
} else {
Expand Down
4 changes: 2 additions & 2 deletions modules/core/src/classes/quaternion.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
// THE SOFTWARE.

import MathArray from '../lib/math-array';
import {checkNumber} from '../lib/common';
import {checkNumber} from '../lib/validators';
import assert from '../lib/assert';

import * as quat from 'gl-matrix/quat';
Expand All @@ -40,7 +40,7 @@ export default class Quaternion extends MathArray {
// Creates a new identity quaternion
// w^2 + x^2 + y^2 + z^2 = 1
constructor(x = 0, y = 0, z = 0, w = 1) {
super(4);
super(-0, -0, -0, -0);
if (Array.isArray(x) && arguments.length === 1) {
this.copy(x);
} else {
Expand Down
15 changes: 12 additions & 3 deletions modules/core/src/classes/vector2.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,23 @@
import Vector from '../lib/vector';
import * as vec2 from 'gl-matrix/vec2';

import {config, isArray} from '../lib/common';
import {checkNumber} from '../lib/validators';

export default class Vector2 extends Vector {
// Creates a new, empty vec2
constructor(x = 0, y = 0) {
super(2);
if (Array.isArray(x) && arguments.length === 1) {
super(-0, -0);
if (isArray(x) && arguments.length === 1) {
this.copy(x);
} else {
this.set(x, y);
if (config.debug) {
checkNumber(x);
checkNumber(y);
}
// PERF NOTE: bitwise or operator ensures JIT-compiler knows we assign only numbers
this[0] = x;
this[1] = y;
}
}

Expand Down
31 changes: 24 additions & 7 deletions modules/core/src/classes/vector3.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
// THE SOFTWARE.

import Vector from '../lib/vector';
import {checkNumber, isArray} from '../lib/common';
import {config, isArray} from '../lib/common';
import {checkNumber, checkVector} from '../lib/validators';

import * as vec3 from 'gl-matrix/vec3';

Expand All @@ -28,20 +29,36 @@ const ORIGIN = [0, 0, 0];
export default class Vector3 extends Vector {
// Creates a new vec3, either empty, or from an array or from values
constructor(x = 0, y = 0, z = 0) {
super(3);
if (Array.isArray(x) && arguments.length === 1) {
super(-0, -0, -0);
if (isArray(x) && arguments.length === 1) {
this.copy(x);
} else {
this.set(x, y, z);
if (config.debug) {
checkNumber(x);
checkNumber(y);
checkNumber(z);
}
// PERF NOTE: bitwise or operator ensures JIT-compiler knows we assign only numbers
this[0] = x;
this[1] = y;
this[2] = z;
}
}

from(arrayOrObject) {
if (isArray(arrayOrObject)) {
this[0] = arrayOrObject.x;
this[1] = arrayOrObject.y;
this[2] = arrayOrObject.z;
if (config.debug) {
checkVector(arrayOrObject, 3);
}
this[0] = arrayOrObject[0];
this[1] = arrayOrObject[1];
this[2] = arrayOrObject[2];
} else {
if (config.debug) {
checkNumber(arrayOrObject.x);
checkNumber(arrayOrObject.y);
checkNumber(arrayOrObject.z);
}
this[0] = arrayOrObject.x;
this[1] = arrayOrObject.y;
this[2] = arrayOrObject.z;
Expand Down
23 changes: 19 additions & 4 deletions modules/core/src/classes/vector4.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,31 @@
// THE SOFTWARE.

import Vector from '../lib/vector';
import {checkNumber} from '../lib/common';
import {config, isArray} from '../lib/common';
import {checkNumber} from '../lib/validators';

export default class Vector4 extends Vector {
// Creates a new, empty vec4
constructor(x = 0, y = 0, z = 0, w = 0) {
super(4);
if (Array.isArray(x) && arguments.length === 1) {
super(-0, -0, -0, -0);
// PERF: Force fields to double precision numbers
this[0] = -0;
this[1] = -0;
this[2] = -0;
this[3] = -0;
if (isArray(x) && arguments.length === 1) {
this.copy(x);
} else {
this.set(x, y, z, w);
if (config.debug) {
checkNumber(x);
checkNumber(y);
checkNumber(z);
checkNumber(w);
}
this[0] = x;
this[1] = y;
this[2] = z;
this[3] = w;
}
}

Expand Down
5 changes: 3 additions & 2 deletions modules/core/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,10 @@ export {default as Matrix3} from './classes/matrix3';
export {default as Matrix4} from './classes/matrix4';
export {default as Quaternion} from './classes/quaternion';

// math.gl "GLSL" functions
export {
// math.gl global utility methods
config,
configure,
checkNumber,
formatValue,
isArray,
clone,
Expand All @@ -51,6 +50,8 @@ export {
lerp
} from './lib/common';

export {checkNumber} from './lib/validators';

export {default as _SphericalCoordinates} from './classes/spherical-coordinates';
export {default as _Pose} from './classes/pose';
export {default as _Euler} from './classes/euler';
Expand Down

0 comments on commit 147b260

Please sign in to comment.