Skip to content

Commit

Permalink
Add benchmarks for node and browser.js (visgl#299)
Browse files Browse the repository at this point in the history
* Add benchmarks on node and browser. Optimize layer construction

* Clean up layer construction optimziation
  • Loading branch information
ibgreen authored and Shaojing Li committed Mar 8, 2017
1 parent 773690b commit c1a7fa6
Show file tree
Hide file tree
Showing 15 changed files with 220 additions and 49 deletions.
4 changes: 3 additions & 1 deletion examples/main/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "deckgl-hello-world-webpack",
"license": "MIT",
"scripts": {
"start": "webpack-dev-server --progress --hot --port 3001 --open"
"start": "webpack-dev-server --progress --hot --open"
},
"dependencies": {
"babel-polyfill": "^6.16.0",
Expand All @@ -15,9 +15,11 @@
"react-stats": "^0.0.5"
},
"devDependencies": {
"benchmark": "^2.1.3",
"brfs": "^1.4.3",
"buble-loader": "^0.4.0",
"json-loader": "^0.5.4",
"raw-loader": "^0.5.1",
"transform-loader": "^0.2.3",
"webpack": "^2.2.0-rc.3",
"webpack-dev-server": "^2.2.0-rc.0",
Expand Down
6 changes: 6 additions & 0 deletions examples/main/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ const LOCAL_DEVELOPMENT_CONFIG = {
},
module: {
rules: [
{
// Inline shaders
test: /\.glsl$/,
loader: 'raw-loader',
exclude: [/node_modules/]
},
{
// Needed to inline deck.gl GLSL shaders
include: [resolve('../../src')],
Expand Down
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<html>
<head>
<meta charset='UTF-8' />
<title>deck.gl example</title>
<title>deck.gl tests</title>
<link href="app.css" rel="stylesheet">
</head>
<body>
Expand Down
10 changes: 7 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,29 @@
"scripts": {
"start": "(cd examples/main && yarn && npm start)",
"compile": "rm -fr dist && buble src -o dist --no modules --y dangerousForOf --objectAssign",
"build": "rm -fr dist && buble src -o dist --no modules --y dangerousForOf --objectAssign && webpack -d --display-modules",
"build": "rnpm run compile && webpack -d --display-modules",
"lint": "eslint src test exhibits/app.js examples",
"publish-prod": "npm run build && npm run test-fast && npm publish",
"publish-beta": "npm run build && npm run test-fast && npm publish --tag beta",
"test": "npm run lint && npm run test-node",
"test-node": "npm run build && node test/node.js",
"test-browser": "webpack-dev-server --config webpack.config.test-browser.js --progress --hot --open",
"test-node": "npm run compile && node test/node.js",
"test-browser": "webpack-dev-server --config webpack.config.test-browser.js --progress --hot --open --port 3010",
"bench-node": "npm run compile && node test/bench/node.js",
"bench-browser": "webpack-dev-server --config webpack.config.bench-browser.js --progress --hot --open --port 3011",
"test-fp64": "(cd test/fp64-test && webpack-dev-server --config webpack.config.test-fp64.js --progress --hot --open)",
"test-rendering": "(cd test/rendering-test && webpack-dev-server --config webpack.config.test-rendering.js --progress --hot --open)"
},
"dependencies": {
"earcut": "^2.0.6",
"file-loader": "^0.9.0",
"gl-matrix": "^2.3.2",
"lodash.flatten": "^4.4.0",
"lodash.flattendeep": "^4.4.0",
"viewport-mercator-project": "3.0.0-beta4"
},
"devDependencies": {
"babel-polyfill": "^6.20.0",
"benchmark": "^2.1.3",
"brfs-babel": "^1.0.0",
"buble": "^0.15.1",
"buble-loader": "^0.4.0",
Expand Down
5 changes: 1 addition & 4 deletions src/layers/core/scatterplot-layer/scatterplot-layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,6 @@ const defaultProps = {
};

export default class ScatterplotLayer extends Layer {
constructor(props) {
super(Object.assign({}, defaultProps, props));
}

getShaders(id) {
return {
vs: readFileSync(join(__dirname, './scatterplot-layer-vertex.glsl'), 'utf8'),
Expand Down Expand Up @@ -162,3 +158,4 @@ export default class ScatterplotLayer extends Layer {
}

ScatterplotLayer.layerName = 'ScatterplotLayer';
ScatterplotLayer.defaultProps = defaultProps;
78 changes: 40 additions & 38 deletions src/lib/layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ const defaultProps = {
opacity: 0.8,
onHover: () => {},
onClick: () => {},
getValue: x => x,
// Update triggers: a key change detection mechanism in deck.gl
// See layer documentation
updateTriggers: {}
Expand All @@ -48,38 +47,27 @@ let counter = 0;

export default class Layer {
/**
* @classdesc
* Base Layer class
*
* @class
* @param {object} props - See docs above
* @param {object} props - See docs and defaults above
*/
constructor(props) {
props = Object.assign({}, defaultProps, props, {
// Accept null as data - otherwise apps will need to add ugly checks
data: props.data || [],
id: props.id || this.constructor.layerName
// If sublayer has static defaultProps member, getDefaultProps will return it
const mergedDefaultProps = getDefaultProps(this);
props = Object.assign({}, mergedDefaultProps, props, {
// Accept null as data - otherwise apps and layers need to add ugly checks
data: props.data || []
});

this.id = props.id;
this.count = counter++;
// this.id = props.id;
this.props = props;
this.oldProps = null;
this.state = null;
this.context = null;
this.count = counter++;
Object.seal(this);

this.validateRequiredProp('id', x => typeof x === 'string');
this.validateRequiredProp('data');
// TODO - allow app to supply dataIterator prop?
// if (props.data) {
// addIterator(props.data);
// if (!props.data[Symbol.iterator]) {
// log.once(0, 'data prop must have iterator');
// }
// }

this._validateDeprecatedProps();
}

toString() {
Expand Down Expand Up @@ -586,26 +574,40 @@ export default class Layer {
this.state.needsRedraw = true;
log(3, 'layer.setUniforms', uniformMap);
}
}

_validateDeprecatedProps() {
if (this.props.isPickable !== undefined) {
log.once(0, 'No isPickable prop in deckgl v3 - use pickable instead');
}
Layer.layerName = 'Layer';
Layer.defaultProps = defaultProps;

// TODO - inject viewport from overlay instead of creating for each layer?
const hasViewportProps =
// this.props.width !== undefined ||
// this.props.height !== undefined ||
this.props.latitude !== undefined ||
this.props.longitude !== undefined ||
this.props.zoom !== undefined ||
this.props.pitch !== undefined ||
this.props.bearing !== undefined;
if (hasViewportProps) {
/* eslint-disable no-console */
// /* global console */
log.once(0,
`deck.gl v3 no longer needs viewport props in Layer ${this}`);
// HELPERS

/*
* Return merged default props stored on layers constructor, create them if needed
*/
function getDefaultProps(layer) {
const {mergedDefaultProps} = layer.constructor;
if (mergedDefaultProps) {
return mergedDefaultProps;
}
return mergeDefaultProps(layer);
}

/*
* Walk the prototype chain and merge all default props
*/
function mergeDefaultProps(layer) {
const {constructor} = layer;
let mergedDefaultProps = {
id: constructor.layerName
};
while (layer) {
const layerDefaultProps = layer.constructor.defaultProps;
if (layerDefaultProps) {
mergedDefaultProps = Object.assign(layerDefaultProps, mergedDefaultProps);
}
layer = Object.getPrototypeOf(layer);
}
// Store for quick lookup
constructor.mergedDefaultProps = mergedDefaultProps;
return mergedDefaultProps;
}
24 changes: 24 additions & 0 deletions test/bench/browser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
require('babel-polyfill');
const _ = require('lodash');
const process = require('process');

const benchmark = require('benchmark');
const Benchmark = benchmark.runInContext({_, process});
/* global window */
window.Benchmark = Benchmark;

/* eslint-disable */
(function () {
const old = console.log;
const logger = document.createElement('div');
document.body.appendChild(logger);
console.log = function f(message) {
if (typeof message === 'object') {
logger.innerHTML += (JSON && JSON.stringify ? JSON.stringify(message) : message) + '<br />';
} else {
logger.innerHTML += message + '<br />';
}
}
})();

require('./index');
64 changes: 64 additions & 0 deletions test/bench/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/* eslint-disable no-console, no-invalid-this */
/* global console */
import {Suite} from 'benchmark';
import * as data from '../data';
import {ScatterplotLayer, ChoroplethLayer} from 'deck.gl';

import {createGLContext} from 'luma.gl';

export function testInitializeLayer({gl, layer}) {
const oldContext = {gl};
const context = {gl};
let failures = 0;
try {
layer.context = context;

layer.initializeLayer({
oldProps: {},
props: layer.props,
oldContext,
context,
changeFlags: layer.diffProps({}, layer.props, context)
});

layer.updateLayer({
oldProps: {},
props: layer.props,
oldContext,
context,
changeFlags: layer.diffProps({}, layer.props, context)
});
} catch (error) {
failures++;
}
return failures;
}

const gl = createGLContext();

const suite = new Suite();

// add tests
suite
.add('ScatterplotLayer#construct', () => {
return new ScatterplotLayer({data: data.choropleths});
})
.add('ChoroplethLayer#construct', () => {
return new ChoroplethLayer({data: data.choropleths});
})
.add('ChoroplethLayer#initialize', () => {
const layer = new ChoroplethLayer({data: data.choropleths});
testInitializeLayer({gl, layer});
})
// add listeners
.on('start', (event) => {
console.log('Starting bench...');
})
.on('cycle', (event) => {
console.log(String(event.target));
})
.on('complete', function t() {
console.log(`Fastest is ${this.filter('fastest').map('name')}`);
})
// run async
.run({delay: 0.1});
20 changes: 20 additions & 0 deletions test/bench/node.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Enables ES2015 import/export in Node.js
require('reify');

// Enables import of glsl
const fs = require('fs');
require.extensions['.glsl'] = function readShader(module, filename) {
module.exports = fs.readFileSync(filename, 'utf8');
};

// Registers an alias for this module
const path = require('path');
const moduleAlias = require('module-alias');
moduleAlias.addAlias('deck.gl', path.resolve('./src'));

require('babel-polyfill');

// Import headless luma support
require('luma.gl/headless');

require('./index');
1 change: 1 addition & 0 deletions test/data/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from '../../examples/main/data-samples';
6 changes: 6 additions & 0 deletions test/node.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
// Enables ES2015 import/export in Node.js
require('reify');

// Enables import of glsl
const fs = require('fs');
require.extensions['.glsl'] = function readShader(module, filename) {
module.exports = fs.readFileSync(filename, 'utf8');
};

// Registers an alias for this module
const path = require('path');
const moduleAlias = require('module-alias');
Expand Down
12 changes: 12 additions & 0 deletions webpack.config.bench-browser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Webpack 2 configuration file for running tests in browser
const {resolve} = require('path');
module.exports = require('./webpack.config.test-browser');

// Replace the entry point for webpack-dev-server
module.exports.entry = {
'test-browser': resolve('./test/bench/browser.js')
};

module.exports.module.noParse = [
/benchmark/
];
10 changes: 10 additions & 0 deletions webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@ module.exports = {

module: {
rules: [
{
// Inline shaders
test: /\.glsl$/,
exclude: /node_modules/,
loader(content) {
this.cacheable && this.cacheable(); // eslint-disable-line
this.value = content;
return "module.exports = " + JSON.stringify(content); // eslint-disable-line
}
},
{
// Compile ES2015 using buble
test: /\.js$/,
Expand Down
6 changes: 6 additions & 0 deletions webpack.config.test-browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ module.exports = {
}
}
},
{
// Inline shaders
test: /\.glsl$/,
exclude: /node_modules/,
loader: 'raw-loader'
},
{
include: [resolve('./src')],
loader: 'transform-loader',
Expand Down
Loading

0 comments on commit c1a7fa6

Please sign in to comment.