ngraph.forcelayout
Version:
Force directed graph drawing layout
110 lines (93 loc) • 2.62 kB
JavaScript
// Comparing the difference of compiled adhoc vs compiled in runtime function execution
// This should let build functions specific to dimension, without affecting performance.
var Benchmark = require('benchmark');
var suite = new Benchmark.Suite;
let bodies;
let total = 0;
let srcCode = staticCompiled.toString().split('\n').slice(1, -1).join('\n');
let dynamicCompiled = compile(srcCode);
resetBodies();
suite.add('static compiled', function() {
for (var i = 0; i < 2000; ++i) {
if (staticCompiled(bodies, 0.5, 0) > 0) {
total = 1;
}
}
})
.add('dynamic pre-compiled', function() {
for (var i = 0; i < 2000; ++i) {
if (dynamicCompiled(bodies, 0.5, 0) > 0) {
total = 1;
}
}
})
.add('dynamic ad-hoc pre-compiled', function() {
let fn = compile(srcCode);
for (var i = 0; i < 2000; ++i) {
if (fn(bodies, 0.5, 0) > 0) {
total = 1;
}
}
})
.on('cycle', function(event) {
console.log(String(event.target), total);
total = 0;
resetBodies();
})
.on('complete', function() {
console.log('Fastest is ' + this.filter('fastest').pluck('name'));
})
// run async
.run({ 'async': true });
function resetBodies() {
bodies = [];
for (let i = 0; i < 100; ++i) {
bodies.push(createBody(i));
}
}
function createBody(i) {
return {
springCount: 0,
springLength: 10,
mass: 1,
force: {x: i, y: i},
velocity: {x: 0, y: 0},
pos: {x: i, y: i}
};
}
function staticCompiled(bodyCollection, timeStep, adaptiveTimeStepWeight) {
var dx = 0, tx = 0,
dy = 0, ty = 0,
i,
max = bodyCollection.length;
if (max === 0) {
return 0;
}
for (i = 0; i < max; ++i) {
var body = bodyCollection[i];
if (adaptiveTimeStepWeight && body.springCount) {
timeStep = (adaptiveTimeStepWeight * body.springLength/body.springCount);
}
var coefficient = timeStep / body.mass;
body.velocity.x += coefficient * body.force.x;
body.velocity.y += coefficient * body.force.y;
var vx = body.velocity.x,
vy = body.velocity.y,
v = Math.sqrt(vx * vx + vy * vy);
if (v > 1) {
// We normalize it so that we move within timeStep range.
// for the case when v <= 1 - we let velocity to fade out.
body.velocity.x = vx / v;
body.velocity.y = vy / v;
}
dx = timeStep * body.velocity.x;
dy = timeStep * body.velocity.y;
body.pos.x += dx;
body.pos.y += dy;
tx += Math.abs(dx); ty += Math.abs(dy);
}
return (tx * tx + ty * ty)/max;
}
function compile(body) {
return new Function('bodies', 'timeStep', 'adaptiveTimeStepWeight', body);
}