Skip to content

Instantly share code, notes, and snippets.

@gmalysa gmalysa/opt_test.js
Last active Dec 20, 2015

Embed
What would you like to do?
Test of some simple function optimizations for javascript/nodejs.
// Test 1: Do simple functions get inlined?
var iter = 10000;
var start, stop;
function inc(a) { return a+1; }
// Wrap test in a function to allow warmup of optimizer
function test1_fn(iter) {
var x;
for (var i = 0; i < iter; ++i) {
x = inc(x);
}
}
// Warmup, then run real test
test1_fn();
start = process.hrtime();
test1_fn();
stop = process.hrtime(start);
time = (stop[0]*1e9 + stop[1])/1e6;
console.log('T1//with function: '+time+' ms');
function test1_inline(iter) {
var x;
for (var i = 0; i < iter; ++i) {
x = x + 1;
}
}
test1_inline(iter);
start = process.hrtime();
test1_inline(iter);
stop = process.hrtime(start);
time = (stop[0]*1e9 + stop[1])/1e6;
console.log('T1//hand inlined: '+time+' ms');
console.log('');
// On my machine, ~ 0.4670 ms vs. 0.0365 ms
// Therefore: the answer is no.
// Test 2: Iteration methods vs. for loops
iter = 1000;
var elems = 100, subelems = 10, sum;
var xa = [];
for (i = 0; i < elems; ++i) {
xa[i] = Math.random();
}
// 2a: array sum with reduce
function test2a_reduce() {
var sum;
sum = xa.reduce(function(memo, v) {
return memo + v;
}, 0);
return sum;
}
sum = test2a_reduce();
start = process.hrtime();
sum = test2a_reduce();
stop = process.hrtime(start);
time = (stop[0]*1e9 + stop[1])/1e6;
console.log('T2A//using reduce: '+time+' ms');
function test2a_loop() {
var sum = 0;
for (var i = 0; i < xa.length; ++i) {
sum += xa[i];
}
return sum;
}
sum = test2a_loop();
start = process.hrtime();
sum = test2a_loop();
stop = process.hrtime(start);
time = (stop[0]*1e9 + stop[1])/1e6;
console.log('T2A//for loop: '+time+' ms');
console.log('');
// On my machine, times fluctuate a lot, but 0.10-0.16 ms vs 0.0054-0.0078 ms
// so the for loop is faster again
// 2b: nested iteration, calling a member function for each element of an array
function t2b_class() {
this.val = Math.random();
}
var t2b_sum = 0;
t2b_class.prototype.work = function() {
t2b_sum += this.val;
};
for (i = 0; i < elems; ++i) {
xa[i] = [];
for (j = 0; j < elems; ++j) {
xa[i][j] = new t2b_class();
}
}
function test2b_nested(xa) {
xa.forEach(function(v) {
v.forEach(function(v2) {
v2.work();
});
});
}
test2b_nested(xa);
start = process.hrtime();
test2b_nested(xa);
stop = process.hrtime(start);
time = (stop[0]*1e9 + stop[1])/1e6;
console.log('T2B//nested iterators: '+time+' ms');
function inner_iter(v2) {
v2.work();
}
function test2b_inner(xa) {
xa.forEach(function(v) {
v.forEach(inner_iter);
});
}
test2b_inner(xa);
start = process.hrtime();
test2b_inner(xa);
stop = process.hrtime(start);
time = (stop[0]*1e9 + stop[1])/1e6;
console.log('T2B//nested iterators, avoids redeclaration: '+time+' ms');
function test2b_loop(xa) {
for (var i = 0; i < xa.length; ++i) {
for (var j = 0; j < xa[i].length; ++j) {
xa[i][j].work();
}
}
}
test2b_loop(xa);
start = process.hrtime();
test2b_loop(xa);
stop = process.hrtime(start);
time = (stop[0]*1e9 + stop[1])/1e6;
console.log('T2B//for loop: '+time+' ms');
console.log('');
// Again, some fluctuation, but roughly 1.08-1.32 ms vs 0.26-0.35 ms on my machine
// Test 3: Tail calls vs. stack walking vs. iterative method
function fact_tail(n, accumulator) {
if (n < 2)
return accumulator;
return fact_tail(n-1, accumulator*n);
}
function fact_stack(n) {
if (n < 2)
return 1;
return n * fact_stack(n-1);
}
function fact_iter(n) {
var accumulator = n;
for (n = n-1; n > 1; --n) {
accumulator = accumulator*n;
}
return accumulator;
}
iter = 1000;
var n = 30, result;
function test3_tail(iter, n) {
var result;
for (var i = 0; i < iter; ++i) {
result = fact_tail(n-1, n);
}
}
test3_tail(iter, n);
start = process.hrtime();
test3_tail(iter, n);
stop = process.hrtime(start);
time = (stop[0]*1e9 + stop[1])/1e6;
console.log('T3//Tail Factorial: '+time+' ms');
function test3_stack(iter, n) {
var result;
for (var i = 0; i < iter; ++i) {
result = fact_stack(n);
}
}
test3_stack(iter, n);
start = process.hrtime();
test3_stack(iter, n);
stop = process.hrtime(start);
time = (stop[0]*1e9 + stop[1])/1e6;
console.log('T3//Stack Factorial: '+time+' ms');
function test3_iter(iter, n) {
var result;
for (var i = 0; i < iter; ++i) {
result = fact_iter(n);
}
}
test3_iter(iter, n);
start = process.hrtime();
test3_iter(iter, n);
stop = process.hrtime(start);
time = (stop[0]*1e9 + stop[1])/1e6;
console.log('T3//Iterative Factorial: '+time+' ms');
console.log('');
// Times: 0.277 ms (tail) vs. 0.515 (stack) vs. 0.181 (iterative)
// Tail and iterative should be the same time if tail calls are fully optimized
// Test 4: Function table overhead
function TestClass(a, b, c) {
this.a = a;
this.b = b;
this.c = c;
}
TestClass.prototype.hypot = function() {
return Math.sqrt(this.a*this.a + this.b*this.b + this.c*this.c);
}
iter = 10000;
var fn = TestClass.prototype.hypot;
xa = new TestClass(Math.random(), Math.random(), Math.random());
function test4_object(iter, xa) {
var result;
for (var i = 0; i < iter; ++i) {
result = xa.hypot();
}
}
test4_object(iter, xa);
start = process.hrtime();
test4_object(iter, xa);
stop = process.hrtime(start);
time = (stop[0]*1e9 + stop[1])/1e6;
console.log('T4//Object method lookup: '+time+' ms');
function test4_prototype(iter, xa) {
var result;
for (var i = 0; i < iter; ++i) {
result = TestClass.prototype.hypot.call(xa);
}
}
test4_prototype(iter, xa);
start = process.hrtime();
test4_prototype(iter, xa);
stop = process.hrtime(start);
time = (stop[0]*1e9 + stop[1])/1e6;
console.log('T4//Prototype method lookup: '+time+' ms');
function test4_pointer(iter, xa) {
var result;
for (var i = 0; i < iter; ++i) {
result = fn.call(xa);
}
}
test4_pointer(iter, xa);
start = process.hrtime();
test4_pointer(iter, xa);
stop = process.hrtime(start);
time = (stop[0]*1e9 + stop[1])/1e6;
console.log('T4//Pre-saved method pointer: '+time+' ms');
console.log('');
// 0.194 ms (lookup) vs 0.172 ms (prototype) vs 0.135 ms (presaved)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.