mirror of
https://github.com/josdejong/mathjs.git
synced 2026-01-18 14:59:29 +00:00
Created some benchmarks for the expression parser
This commit is contained in:
parent
943a99df71
commit
fb8a4e0a0e
@ -1,41 +1,32 @@
|
||||
# Benchmarks
|
||||
|
||||
These are some rough benchmarks to get an idea of the performance of math.js compared to other JavaScript libraries and to Octave (C++). They only give an _indication_ of the order of magnitude difference meant to see were math.js has room for improvements, it's not a fully fletched benchmark suite.
|
||||
|
||||
This directory contains benchmarks which can be used when working on
|
||||
performance improvements of math.js.
|
||||
|
||||
## How to run
|
||||
|
||||
### JavaScript library benchmarks
|
||||
|
||||
Install the dependencies once:
|
||||
To run all benchmarks:
|
||||
|
||||
```
|
||||
npm install
|
||||
node index.js
|
||||
```
|
||||
|
||||
run the tests:
|
||||
To run a single set of benchmarks:
|
||||
|
||||
```
|
||||
node benchmark.js
|
||||
node expression_parser.js
|
||||
```
|
||||
|
||||
### Octave benchmarks
|
||||
## Octave benchmarks
|
||||
|
||||
Open Octave, run the script `benchmark_octave.m`
|
||||
For matrix operations, there is a small benchmark for Octave.
|
||||
Open Octave, run the script `matrix_operations_octave.m`
|
||||
|
||||
## To do
|
||||
|
||||
- compare with python and Octave
|
||||
|
||||
- compare matrix operations with python
|
||||
- use larger matrix, like 250x250 instead of 25x25
|
||||
|
||||
- Compare expression parsers
|
||||
|
||||
evaluate the following function thousand times
|
||||
|
||||
f(x) = (sin(x) + cos(x/2)) * 5
|
||||
|
||||
Libraries:
|
||||
- math.js
|
||||
- expr-eval
|
||||
- jsep
|
||||
|
||||
34
benchmark/expression_parser.js
Normal file
34
benchmark/expression_parser.js
Normal file
@ -0,0 +1,34 @@
|
||||
// test performance of the expression parser in node.js
|
||||
|
||||
var Benchmark = require('benchmark');
|
||||
var padRight = require('pad-right');
|
||||
var math = require('../index');
|
||||
|
||||
function pad (text) {
|
||||
return padRight(text, 40, ' ');
|
||||
}
|
||||
|
||||
var expr = '2 + 3 * sin(pi / 4) - 4x';
|
||||
var scope = {x: 2};
|
||||
var compiled = math.parse(expr).compile();
|
||||
|
||||
var suite = new Benchmark.Suite();
|
||||
suite
|
||||
.add(pad('expression parse and evaluate'), function() {
|
||||
var res = math.eval(expr, scope);
|
||||
})
|
||||
.add(pad('expression parse and compile'), function() {
|
||||
var c = math.parse('2 + 3 * sin(pi / 4) - 4x').compile();
|
||||
})
|
||||
.add(pad('expression parse'), function() {
|
||||
var node = math.parse('2 + 3 * sin(pi / 4) - 4x');
|
||||
})
|
||||
.add(pad('evaluate'), function() {
|
||||
var res = compiled.eval(scope);
|
||||
})
|
||||
.on('cycle', function(event) {
|
||||
console.log(String(event.target));
|
||||
})
|
||||
.on('complete', function() {
|
||||
})
|
||||
.run();
|
||||
3
benchmark/index.js
Normal file
3
benchmark/index.js
Normal file
@ -0,0 +1,3 @@
|
||||
// run all benchmarks
|
||||
require ('./expression_parser');
|
||||
require ('./matrix_operations');
|
||||
@ -1,13 +1,21 @@
|
||||
/**
|
||||
* Benchmark
|
||||
*
|
||||
* Compare performance of basic matrix operations of a number of math libraries.
|
||||
* Compare performance of basic matrix operations of a number of math libraries.
|
||||
*
|
||||
* These are some rough benchmarks to get an idea of the performance of math.js
|
||||
* compared to other JavaScript libraries and to Octave (C++). They only give an
|
||||
* _indication_ of the order of magnitude difference meant to see were math.js
|
||||
* has room for improvements, it's not a fully fletched benchmark suite.
|
||||
*/
|
||||
|
||||
var padLeft = require('pad-left')
|
||||
var padRight = require('pad-right')
|
||||
var Benchmark = require('benchmark');
|
||||
var padRight = require('pad-right');
|
||||
var suite = new Benchmark.Suite();
|
||||
|
||||
var iterations = 1000
|
||||
function pad (text) {
|
||||
return padRight(text, 40, ' ');
|
||||
}
|
||||
|
||||
// fiedler matrix 25 x 25
|
||||
var fiedler = [
|
||||
@ -36,89 +44,62 @@ var fiedler = [
|
||||
[22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2],
|
||||
[23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 1],
|
||||
[24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
|
||||
]
|
||||
];
|
||||
|
||||
// mathjs
|
||||
{
|
||||
var math = require('../index')
|
||||
var A = math.matrix(fiedler)
|
||||
(function () {
|
||||
var math = require('../index');
|
||||
var A = math.matrix(fiedler);
|
||||
var res;
|
||||
|
||||
measure ('mathjs', 'A+A', function () { res = math.add(A, A) })
|
||||
measure ('mathjs', 'A*A', function () { res = math.multiply(A, A) })
|
||||
measure ('mathjs', 'A\'', function () { res = math.transpose(A) })
|
||||
measure ('mathjs', 'det(A)', function () { res = math.det(A) })
|
||||
}
|
||||
suite.add(pad('matrix operations mathjs A+A'), function () { res = math.add(A, A) });
|
||||
suite.add(pad('matrix operations mathjs A*A'), function () { res = math.multiply(A, A) });
|
||||
suite.add(pad('matrix operations mathjs A\''), function () { res = math.transpose(A) });
|
||||
suite.add(pad('matrix operations mathjs det(A)'), function () { res = math.det(A) });
|
||||
})();
|
||||
|
||||
// sylvester
|
||||
{
|
||||
var sylvester = require('sylvester')
|
||||
var A = sylvester.Matrix.create(fiedler)
|
||||
(function () {
|
||||
var sylvester = require('sylvester');
|
||||
var A = sylvester.Matrix.create(fiedler);
|
||||
|
||||
measure ('sylvester', 'A+A', function () { A.add(A) })
|
||||
measure ('sylvester', 'A*A', function () { A.multiply(A) })
|
||||
measure ('sylvester', 'A\'', function () { A.transpose() })
|
||||
measure ('sylvester', 'det(A)', function () { A.det() })
|
||||
}
|
||||
suite.add(pad('matrix operations sylvester A+A'), function () { A.add(A) });
|
||||
suite.add(pad('matrix operations sylvester A*A'), function () { A.multiply(A) });
|
||||
suite.add(pad('matrix operations sylvester A\''), function () { A.transpose() });
|
||||
suite.add(pad('matrix operations sylvester det(A)'), function () { A.det() });
|
||||
})();
|
||||
|
||||
// numericjs
|
||||
{
|
||||
var numeric = require('numericjs')
|
||||
var A = fiedler
|
||||
(function () {
|
||||
var numeric = require('numericjs');
|
||||
var A = fiedler;
|
||||
|
||||
measure ('numericjs', 'A+A', function () { numeric.add(A, A) })
|
||||
measure ('numericjs', 'A*A', function () { numeric.dot(A, A) })
|
||||
measure ('numericjs', 'A\'', function () { numeric.transpose(A) })
|
||||
measure ('numericjs', 'det(A)', function () { numeric.det(A) })
|
||||
}
|
||||
suite.add(pad('matrix operations numericjs A+A'), function () { numeric.add(A, A) });
|
||||
suite.add(pad('matrix operations numericjs A*A'), function () { numeric.dot(A, A) });
|
||||
suite.add(pad('matrix operations numericjs A\''), function () { numeric.transpose(A) });
|
||||
suite.add(pad('matrix operations numericjs det(A)'), function () { numeric.det(A) });
|
||||
})();
|
||||
|
||||
// ndarray
|
||||
{
|
||||
var ndarray = require('ndarray')
|
||||
var gemm = require('ndarray-gemm')
|
||||
var zeros = require('zeros')
|
||||
var ops = require('ndarray-ops')
|
||||
var pack = require('ndarray-pack')
|
||||
var det = require('ndarray-determinant')
|
||||
(function () {
|
||||
var ndarray = require('ndarray');
|
||||
var gemm = require('ndarray-gemm');
|
||||
var zeros = require('zeros');
|
||||
var ops = require('ndarray-ops');
|
||||
var pack = require('ndarray-pack');
|
||||
var det = require('ndarray-determinant');
|
||||
|
||||
var A = pack(fiedler)
|
||||
var B = zeros([25, 25])
|
||||
var A = pack(fiedler);
|
||||
var B = zeros([25, 25]);
|
||||
|
||||
measure('ndarray', 'A+A', function () { ops.add(B, A, A) })
|
||||
measure('ndarray', 'A*A', function () { gemm(B, A, A) })
|
||||
measure('ndarray', 'A\'', function () { ops.assign(B, A); B.transpose(1, 0); })
|
||||
measure('ndarray', 'det(A)', function () { det(A) })
|
||||
}
|
||||
suite.add(pad('matrix operations ndarray A+A'), function () { ops.add(B, A, A) });
|
||||
suite.add(pad('matrix operations ndarray A*A'), function () { gemm(B, A, A) });
|
||||
suite.add(pad('matrix operations ndarray A\''), function () { ops.assign(B, A); B.transpose(1, 0); });
|
||||
suite.add(pad('matrix operations ndarray det(A)'), function () { det(A) });
|
||||
})();
|
||||
|
||||
/**
|
||||
* Repeatedly execute test and print the average duration
|
||||
* @param {string} library
|
||||
* @param {string} description
|
||||
* @param {function} test
|
||||
*/
|
||||
function measure (library, description, test) {
|
||||
// warm up
|
||||
test()
|
||||
|
||||
var start = Date.now()
|
||||
for (var i = 0; i < iterations / 10; i++) {
|
||||
// ten times to minimize the impact of the duration of the for loop itself
|
||||
test()
|
||||
test()
|
||||
test()
|
||||
test()
|
||||
test()
|
||||
test()
|
||||
test()
|
||||
test()
|
||||
test()
|
||||
test()
|
||||
}
|
||||
var end = Date.now()
|
||||
var duration = Math.round((end - start) * 1000 / (iterations)) // in microseconds
|
||||
|
||||
console.log(padRight(library, 12, ' ') + padRight(description, 8, ' ') + padLeft(duration, 6, ' ') + ' microseconds')
|
||||
}
|
||||
|
||||
function flatten (arr) {
|
||||
return [].concat.apply([], arr)
|
||||
}
|
||||
suite
|
||||
.on('cycle', function(event) {
|
||||
console.log(String(event.target));
|
||||
})
|
||||
.run();
|
||||
@ -1,17 +0,0 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"expr-eval": "1.0.0",
|
||||
"jsep": "0.3.0",
|
||||
"math-expression-evaluator": "1.2.16",
|
||||
"ndarray": "1.0.18",
|
||||
"ndarray-determinant": "1.0.0",
|
||||
"ndarray-gemm": "1.0.0",
|
||||
"ndarray-ops": "1.2.2",
|
||||
"ndarray-pack": "1.2.1",
|
||||
"numericjs": "1.2.6",
|
||||
"pad-left": "2.1.0",
|
||||
"pad-right": "0.2.2",
|
||||
"sylvester": "0.0.21",
|
||||
"zeros": "1.0.0"
|
||||
}
|
||||
}
|
||||
3390
package-lock.json
generated
Normal file
3390
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
24
package.json
24
package.json
@ -81,25 +81,38 @@
|
||||
"unit"
|
||||
],
|
||||
"dependencies": {
|
||||
"seed-random": "2.2.0",
|
||||
"tiny-emitter": "1.0.2",
|
||||
"complex.js": "2.0.1",
|
||||
"decimal.js": "7.1.1",
|
||||
"fraction.js": "4.0.0",
|
||||
"complex.js": "2.0.1",
|
||||
"seed-random": "2.2.0",
|
||||
"tiny-emitter": "1.0.2",
|
||||
"typed-function": "0.10.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"benchmark": "2.1.4",
|
||||
"expr-eval": "1.0.0",
|
||||
"glob": "7.1.1",
|
||||
"gulp": "3.9.1",
|
||||
"gulp-util": "3.0.8",
|
||||
"istanbul": "0.4.5",
|
||||
"jsep": "0.3.0",
|
||||
"math-expression-evaluator": "1.2.16",
|
||||
"mkdirp": "0.5.1",
|
||||
"mocha": "3.2.0",
|
||||
"ndarray": "1.0.18",
|
||||
"ndarray-determinant": "1.0.0",
|
||||
"ndarray-gemm": "1.0.0",
|
||||
"ndarray-ops": "1.2.2",
|
||||
"ndarray-pack": "1.2.1",
|
||||
"numericjs": "1.2.6",
|
||||
"pad-right": "0.2.2",
|
||||
"q": "1.4.1",
|
||||
"sylvester": "0.0.21",
|
||||
"tar": "2.2.1",
|
||||
"uglify-js": "2.7.5",
|
||||
"underscore": "1.8.3",
|
||||
"webpack": "2.2.1"
|
||||
"webpack": "2.2.1",
|
||||
"zeros": "1.0.0"
|
||||
},
|
||||
"main": "./index",
|
||||
"scripts": {
|
||||
@ -114,5 +127,6 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.1"
|
||||
}
|
||||
},
|
||||
"false": {}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user