Skip to content

Commit

Permalink
Stress test
Browse files Browse the repository at this point in the history
  • Loading branch information
tsherif committed Sep 24, 2019
1 parent ed58a63 commit c4fe79e
Show file tree
Hide file tree
Showing 8 changed files with 282 additions and 14 deletions.
2 changes: 1 addition & 1 deletion modules/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"gl-matrix": "^3.0.0",
"math.gl": "^3.0.0",
"mjolnir.js": "^2.1.2",
"probe.gl": "^3.1.0",
"probe.gl": "^3.1.1",
"seer": "^0.2.4",
"viewport-mercator-project": "^6.1.0"
}
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@
},
"devDependencies": {
"@luma.gl/effects": "^7.3.0-beta.2",
"@probe.gl/bench": "^3.1.0",
"@probe.gl/test-utils": "^3.1.0",
"@probe.gl/bench": "^3.1.1",
"@probe.gl/test-utils": "^3.1.1",
"@loaders.gl/polyfills": "1.3.1",
"babel-loader": "^8.0.0",
"babel-plugin-inline-webgl-constants": "^1.0.1",
Expand Down
24 changes: 24 additions & 0 deletions test/apps/stress-tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<div align="center">
<img width="150" heigth="150" src="https://webpack.js.org/assets/icon-square-big.svg" />
</div>

## Example: Frustum Cull

Demonstrate frustum plane extraction and tests.

Uses [Webpack](https://github.com/webpack/webpack) to bundle files and serves it
with [webpack-dev-server](https://webpack.js.org/guides/development/#webpack-dev-server).

## Usage

To install dependencies:

```bash
npm install
# or
yarn
```

Commands:
* `npm start` is the development target, to serves the app and hot reload.
* `npm run build` is the production target, to create the final bundle and write to disk.
127 changes: 127 additions & 0 deletions test/apps/stress-tests/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/* global window */

import React, {Component} from 'react';
import {render} from 'react-dom';
import DeckGL, {ScatterplotLayer} from 'deck.gl';
import {StaticMap} from 'react-map-gl';
import {RenderMetrics} from './render-metrics';

const NUM_LAYERS = 1000;
const POINTS_PER_LAYER = 100;
const SF_MIN = [-122.511289, 37.709481];
const SF_MAX = [-122.37646761, 37.806013];

function sfRandomPoints(numPoints, maxVal) {
const points = new Array(numPoints);

const lngMin = SF_MIN[0];
const latMin = SF_MIN[1];
const lngRange = SF_MAX[0] - SF_MIN[0];
const latRange = SF_MAX[1] - SF_MIN[1];

for (let i = 0; i < numPoints; ++i) {
points[i] = {
position: [lngMin + Math.random() * lngRange, latMin + Math.random() * latRange],
value: Math.random() * maxVal
};
}

return points;
}

class Root extends Component {
constructor(props) {
super(props);
this.deckRef = React.createRef();

this.state = {
mapViewState: {
latitude: 37.752,
longitude: -122.427,
zoom: 11.5,
pitch: 0,
bearing: 0
},
metrics: null
};

this.layers = new Array(NUM_LAYERS);

this.cameraShakeHandle = null;
this._cameraShake = this._cameraShake.bind(this);
this._onMetrics = this._onMetrics.bind(this);

this._initializeLayers();
}

componentDidMount() {
this.cameraShakeHandle = window.requestAnimationFrame(this._cameraShake);
}

componentWillUnmount() {
window.cancelAnimationFrame(this.cameraShakeHandle);
}

_initializeLayers() {
for (let i = 0; i < NUM_LAYERS; ++i) {
const r = Math.random() * 256;
const g = Math.random() * 256;
const b = Math.random() * 256;
this.layers[i] = new ScatterplotLayer({
data: sfRandomPoints(POINTS_PER_LAYER, 10),
id: `scatterplotLayer${i}`,
getPosition: d => d.position,
getFillColor: [r, g, b],
getRadius: d => d.value,
opacity: 1,
pickable: true,
radiusScale: 30,
radiusMinPixels: 1,
radiusMaxPixels: 30
});
}
}

_cameraShake() {
this.cameraShakeHandle = window.requestAnimationFrame(this._cameraShake);
if (this.deckRef.current) {
const deck = this.deckRef.current.deck;
const viewState = deck.viewManager.getViewState();
deck.setProps({
viewState: Object.assign({}, viewState, {
latitude: viewState.latitude + (Math.random() * 0.00002 - 0.00001),
longitude: viewState.longitude + (Math.random() * 0.00002 - 0.00001)
})
});
}
}

_onMetrics(metrics) {
this.setState({metrics: Object.assign({}, metrics)});
}

render() {
return (
<div>
<div style={{position: 'absolute', top: '10px', left: '100px', zIndex: 999}}>
<div>
Rendering {NUM_LAYERS * POINTS_PER_LAYER} points in {NUM_LAYERS} layers.
</div>
<RenderMetrics metrics={this.state.metrics} />
</div>
<DeckGL
controller={true}
viewState={this.state.mapViewState}
ref={this.deckRef}
layers={this.layers}
_onMetrics={this._onMetrics}
>
<StaticMap key="map" mapStyle="mapbox://styles/mapbox/light-v9" />
</DeckGL>
</div>
);
}
}

/* global document */
render(<Root />, document.body.appendChild(document.createElement('div')));
24 changes: 24 additions & 0 deletions test/apps/stress-tests/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "frustum-cull",
"version": "0.0.0",
"license": "MIT",
"scripts": {
"start": "webpack-dev-server --progress --hot --open",
"start-local": "webpack-dev-server --env.local --progress --hot --open",
"build": "webpack -p"
},
"dependencies": {
"react": "^16.3.0",
"react-dom": "^16.3.0",
"react-map-gl": "^4.1.2"
},
"devDependencies": {
"@babel/core": "^7.0.0",
"@babel/preset-react": "^7.0.0",
"babel-loader": "^8.0.5",
"html-webpack-plugin": "^3.0.7",
"webpack": "^4.20.2",
"webpack-cli": "^3.1.2",
"webpack-dev-server": "^3.1.1"
}
}
49 changes: 49 additions & 0 deletions test/apps/stress-tests/render-metrics.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import React from 'react';

const kB = 1024;
const MB = 1024 * 1024;
const GB = 1024 * 1024 * 1024;

export function RenderMetrics(props) {
const metrics = props.metrics;

if (!metrics) {
return null;
}

return (
<div>
<div>FPS: {Math.round(metrics.fps)}</div>
<div>
GPU Frame Time: {metrics.gpuTimePerFrame.toFixed(2)}
ms
</div>
<div>
CPU Frame Time: {metrics.cpuTimePerFrame.toFixed(2)}
ms
</div>
<div>GPU Memory: {formatMemory(metrics.gpuMemory)}</div>
</div>
);
}

function formatMemory(mem) {
let unit;
let val;

if (mem < kB) {
val = mem;
unit = ' bytes';
} else if (mem < MB) {
val = mem / kB;
unit = 'kB';
} else if (mem < GB) {
val = mem / MB;
unit = 'MB';
} else {
val = mem / GB;
unit = 'GB';
}

return `${val.toFixed(2)}${unit}`;
}
37 changes: 37 additions & 0 deletions test/apps/stress-tests/webpack.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// NOTE: To use this example standalone (e.g. outside of deck.gl repo)
// delete the local development overrides at the bottom of this file

// avoid destructuring for older Node version support
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');

const CONFIG = {
mode: 'development',

entry: {
app: './app.js'
},

module: {
rules: [
{
// Transpile ES6 to ES5 with babel
// Remove if your app does not use JSX or you don't need to support old browsers
test: /\.js$/,
loader: 'babel-loader',
exclude: [/node_modules/],
options: {
presets: ['@babel/preset-react']
}
}
]
},

plugins: [
new HtmlWebpackPlugin({title: 'deck.gl Stress Test'}),
new webpack.EnvironmentPlugin(['MapboxAccessToken'])
]
};

// This line enables bundling against src in this repo rather than installed module
module.exports = env => (env ? require('../webpack.config.local')(CONFIG)(env) : CONFIG);
29 changes: 18 additions & 11 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1912,22 +1912,22 @@
"@phosphor/signaling" "^1.3.0"
"@phosphor/virtualdom" "^1.2.0"

"@probe.gl/bench@^3.1.0":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@probe.gl/bench/-/bench-3.1.0.tgz#30aa5de961e4b50023642671389cdea3c71c53ee"
integrity sha512-X57uX3xCrUm66+kDOsCEsRJGpNBrrHqB10VzXM3xtmArM54AG/NAaIdUQmiBVhm/sKIK0DuoqcNI51OSniQf5Q==
"@probe.gl/bench@^3.1.1":
version "3.1.1"
resolved "https://registry.yarnpkg.com/@probe.gl/bench/-/bench-3.1.1.tgz#caba3f7fabd0149f1b6fb28db27adc7ef454f813"
integrity sha512-opy3rdUqgz+GRQ5aam49UKZXIERZMCE7eLQm9uKaTTghdy/UJswKbRKcJc2mbk5k3sOyLILLZPJrIxfvfNSAbQ==
dependencies:
"@babel/runtime" "^7.0.0"
probe.gl "3.1.0"
probe.gl "3.1.1"

"@probe.gl/test-utils@^3.1.0":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@probe.gl/test-utils/-/test-utils-3.1.0.tgz#839ebb4802bcbe23e80523f3d9fd783af02b1b09"
integrity sha512-kxtnHnnno7U/CED2FhQEpwq/8aEEJL93UrtBpu7GQ7ICi1DIBOQaHlMLkeFeRxo0qAuV0X1Bi1tgkJh5h2FGRw==
"@probe.gl/test-utils@^3.1.1":
version "3.1.1"
resolved "https://registry.yarnpkg.com/@probe.gl/test-utils/-/test-utils-3.1.1.tgz#3ffb632b590ae82ae40011e520be0a2e5eb94059"
integrity sha512-jeOficrZ6zEc38kQTLVfj98GHb551EHv17QSUPTB2lr7grhD2juA+g0h7mmQWW6QNVEzXkJROo2Bv2LO1Ci5Fw==
dependencies:
"@babel/runtime" "^7.0.0"
pixelmatch "^4.0.2"
probe.gl "3.1.0"
probe.gl "3.1.1"
puppeteer "^1.16.0"

"@types/backbone@^1.3.33":
Expand Down Expand Up @@ -8410,7 +8410,14 @@ private@^0.1.6:
resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff"
integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==

probe.gl@3.1.0, probe.gl@^3.1.0:
probe.gl@3.1.1, probe.gl@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/probe.gl/-/probe.gl-3.1.1.tgz#58f5d23efe588b9d9af10add6b47587f8e6c72b3"
integrity sha512-mD/DzhaYVftrRpobJd/W5JNhDVYCpClhuCGeOphuNZO1+qM6tOlBIf/6ETz11JyolZoJTTeT6aiVXOuIVyAVRg==
dependencies:
"@babel/runtime" "^7.0.0"

probe.gl@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/probe.gl/-/probe.gl-3.1.0.tgz#6aaeeb2d5bff85458fb7e8f7a72a57a53757c745"
integrity sha512-Bqk+hMklRtHJ29UcDvhjh0ha0JLoZI5wpPBZdzAOwciBGhPXNy1C/TD1ihKBdOlCzTw78EKVLm0eKLj5Xek5+w==
Expand Down

0 comments on commit c4fe79e

Please sign in to comment.