Skip to content

Commit

Permalink
Add benchmarks (#48)
Browse files Browse the repository at this point in the history
* Issue #46: Add ability to cancel an instance

`findPath()` now returns a unique number (even across multiple instances of easystar).  There's a new method `cancelPath()` which can be used to cancel a path calculation.

This can be used to avoid wasting effort, for instance if a game actor dies or changes its destination before the path is computed.

* Cleanup, and have cancelPath return boolean

* Missed a spot renaming _nextId.

Add a test case confirming that two instances have different IDs, which might have caught this mistake.

* Convert instances from array to map

Add instanceQueue to maintain the calculation order.  This change should make cancelling paths O(1) rather than O(n).

* update index.d.ts for path canelling changes.

* Add karma-benchmark, and some benchmarks.

There are two grids benchmarked:  One is maze-like, so the search will be deep but narrow.  The other is a mostly open field, so the search will be short but with more branches.

For both grids, the benchmarks are run three different ways: With no diagonals, diagonals but no corner-cutting, and diagonals with corner-cutting.

* Add karma-benchmark, and some benchmarks.

There are two grids benchmarked:  One is maze-like, so the search will be deep but narrow.  The other is a mostly open field, so the search will be short but with more branches.

For both grids, the benchmarks are run three different ways: With no diagonals, diagonals but no corner-cutting, and diagonals with corner-cutting.

* Bump version to 0.4.0

* Use synchronous benchmarks

Because these benchmarks use `enableAsync` there is no need to use the benchmarkjs `defer` flag.  This seems to avoid potential "Maximum call stack size exceeded" errors when the benchmarks are fast (possible bug in karma-benchmark).

* Add karma-benchmark, and some benchmarks.

There are two grids benchmarked:  One is maze-like, so the search will be deep but narrow.  The other is a mostly open field, so the search will be short but with more branches.

For both grids, the benchmarks are run three different ways: With no diagonals, diagonals but no corner-cutting, and diagonals with corner-cutting.

* Use synchronous benchmarks

Because these benchmarks use `enableAsync` there is no need to use the benchmarkjs `defer` flag.  This seems to avoid potential "Maximum call stack size exceeded" errors when the benchmarks are fast (possible bug in karma-benchmark).

* Add a 1000x1000 benchmark.

This pushes the limits of `karma-benchmarkjs-reporter`, in that it doesn't show precise results when ops take more than one second.

But a test like this is important to avoid optimizing the small-grid case at the expense of the large-grid case.
  • Loading branch information
sbj42 authored and prettymuchbryce committed Apr 3, 2017
1 parent 07680f1 commit aa30ae6
Show file tree
Hide file tree
Showing 3 changed files with 235 additions and 0 deletions.
75 changes: 75 additions & 0 deletions karma.benchmark.conf.js
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,75 @@
// Karma configuration
// Generated on Sun Nov 17 2013 05:27:43 GMT-0500 (EST)

module.exports = function(config) {
config.set({

// base path, that will be used to resolve files and exclude
basePath: './',

plugins: [
'karma-benchmark',
'karma-benchmarkjs-reporter',
'karma-phantomjs-launcher'
],


// frameworks to use
frameworks: ['benchmark'],


// list of files / patterns to load in the browser
files: [
'./bin/easystar-0.3.1.js',
'./test/easystarbenchmark.js'
],


// list of files to exclude
exclude: [

],


// test results reporter to use
// possible values: 'dots', 'progress', 'junit', 'growl', 'coverage'
reporters: ['benchmark'],


// web server port
port: 9876,


// enable / disable colors in the output (reporters and logs)
colors: true,


// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,


// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,


// Start these browsers, currently available:
// - Chrome
// - ChromeCanary
// - Firefox
// - Opera (has to be installed with `npm install karma-opera-launcher`)
// - Safari (only Mac; has to be installed with `npm install karma-safari-launcher`)
// - PhantomJS
// - IE (only Windows; has to be installed with `npm install karma-ie-launcher`)
//browsers: ['PhantomJS'],


// If browser does not capture in given timeout [ms], kill it
captureTimeout: 60000,


// Continuous Integration mode
// if true, it capture browsers, run tests and exit
singleRun: false
});
};
3 changes: 3 additions & 0 deletions package.json
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"scripts": { "scripts": {
"build": "webpack && webpack --minify", "build": "webpack && webpack --minify",
"test": "./node_modules/karma/bin/karma start ./karma.conf.js", "test": "./node_modules/karma/bin/karma start ./karma.conf.js",
"benchmark": "./node_modules/karma/bin/karma start ./karma.benchmark.conf.js",
"watch": "webpack -w" "watch": "webpack -w"
}, },
"keywords": [ "keywords": [
Expand All @@ -31,6 +32,8 @@
"babel-loader": "^6.2.4", "babel-loader": "^6.2.4",
"jasmine-core": "^2.5.1", "jasmine-core": "^2.5.1",
"karma": "^0.12.16", "karma": "^0.12.16",
"karma-benchmark": "^0.7.1",
"karma-benchmarkjs-reporter": "^1.0.0",
"karma-coverage": "^0.2.4", "karma-coverage": "^0.2.4",
"karma-jasmine": "^0.3.5", "karma-jasmine": "^0.3.5",
"karma-phantomjs-launcher": "^0.1.4", "karma-phantomjs-launcher": "^0.1.4",
Expand Down
157 changes: 157 additions & 0 deletions test/easystarbenchmark.js
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,157 @@
var easyStar;
function onPathFound() { }
function setup10x10maze() {
easyStar = new EasyStar.js();
var map = [
[1,1,1,1,1,0,1,0,1,1],
[0,0,0,0,1,0,1,0,1,0],
[1,1,1,1,1,1,1,0,1,1],
[1,0,1,0,0,0,0,0,0,1],
[1,0,1,1,0,1,1,1,0,1],
[1,0,0,0,0,1,0,1,0,1],
[1,1,1,1,0,1,0,1,0,1],
[0,0,0,1,0,1,0,1,1,1],
[0,1,1,1,0,1,0,1,0,1],
[1,1,0,1,1,1,0,1,1,1]
];

easyStar.setGrid(map);
easyStar.setAcceptableTiles([1]);
easyStar.enableSync();
}
function setup10x10field() {
easyStar = new EasyStar.js();
var map = [
[1,1,1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1,1,1],
[1,1,1,1,0,0,1,1,1,1],
[1,1,1,1,0,0,1,1,1,1],
[1,1,1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1,1,1]
];

easyStar.setGrid(map);
easyStar.setAcceptableTiles([1]);
easyStar.enableSync();
}
function setup1000x1000field() {
easyStar = new EasyStar.js();
var map = [];
for (var y = 0; y < 1000; y ++) {
var row = [];
for (var x = 0; x < 1000; x ++) {
row.push(1);
}
map.push(row);
}

easyStar.setGrid(map);
easyStar.setAcceptableTiles([1]);
easyStar.enableSync();
}

suite('EasyStar.js', function() {
benchmark('10x10 maze no diagonals', {
fn: function() {
easyStar.findPath(0,0,9,0,onPathFound);
easyStar.calculate();
},
setup: function() {
setup10x10maze();
easyStar.disableDiagonals();
easyStar.disableCornerCutting();
}
});
benchmark('10x10 maze diagonals but no corner-cutting', {
fn: function() {
easyStar.findPath(0,0,9,0,onPathFound);
easyStar.calculate();
},
setup: function() {
setup10x10maze();
easyStar.enableDiagonals();
easyStar.disableCornerCutting();
}
});
benchmark('10x10 maze diagonals and corner-cutting', {
fn: function() {
easyStar.findPath(0,0,9,0,onPathFound);
easyStar.calculate();
},
setup: function() {
setup10x10maze();
easyStar.enableDiagonals();
easyStar.enableCornerCutting();
}
});
benchmark('10x10 field no diagonals', {
fn: function() {
easyStar.findPath(0,0,9,9,onPathFound);
easyStar.calculate();
},
setup: function() {
setup10x10field();
easyStar.disableDiagonals();
easyStar.disableCornerCutting();
}
});
benchmark('10x10 field diagonals but no corner-cutting', {
fn: function() {
easyStar.findPath(0,0,9,9,onPathFound);
easyStar.calculate();
},
setup: function() {
setup10x10field();
easyStar.enableDiagonals();
easyStar.disableCornerCutting();
}
});
benchmark('10x10 field diagonals and corner-cutting', {
fn: function() {
easyStar.findPath(0,0,9,9,onPathFound);
easyStar.calculate();
},
setup: function() {
setup10x10field();
easyStar.enableDiagonals();
easyStar.enableCornerCutting();
}
});
benchmark('1000x1000 field no diagonals', {
fn: function() {
easyStar.findPath(0,0,999,999,onPathFound);
easyStar.calculate();
},
setup: function() {
setup1000x1000field();
easyStar.disableDiagonals();
easyStar.disableCornerCutting();
}
});
benchmark('1000x1000 field diagonals but no corner-cut', {
fn: function() {
easyStar.findPath(0,0,999,999,onPathFound);
easyStar.calculate();
},
setup: function() {
setup1000x1000field();
easyStar.enableDiagonals();
easyStar.disableCornerCutting();
}
});
benchmark('1000x1000 field diagonals and corner-cut', {
fn: function() {
easyStar.findPath(0,0,999,999,onPathFound);
easyStar.calculate();
},
setup: function() {
setup1000x1000field();
easyStar.enableDiagonals();
easyStar.enableCornerCutting();
}
});
});

0 comments on commit aa30ae6

Please sign in to comment.