396 lines
13 KiB
Plaintext
396 lines
13 KiB
Plaintext
var time = use('time')
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// JavaScript Performance Benchmark Suite
|
|
// Tests core JS operations: property access, function calls, arithmetic, etc.
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Test configurations
|
|
const iterations = {
|
|
simple: 10000000,
|
|
medium: 1000000,
|
|
complex: 100000
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Utility: measureTime(fn) => how long fn() takes in seconds
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
function measureTime(fn) {
|
|
var start = time.number();
|
|
fn();
|
|
var end = time.number();
|
|
return (end - start);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Benchmark: Property Access
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
function benchPropertyAccess() {
|
|
var obj = {
|
|
a: 1, b: 2, c: 3, d: 4, e: 5,
|
|
nested: { x: 10, y: 20, z: 30 }
|
|
};
|
|
|
|
var readTime = measureTime(function() {
|
|
var sum = 0;
|
|
for (var i = 0; i < iterations.simple; i++) {
|
|
sum += obj.a + obj.b + obj.c + obj.d + obj.e;
|
|
sum += obj.nested.x + obj.nested.y + obj.nested.z;
|
|
}
|
|
});
|
|
|
|
var writeTime = measureTime(function() {
|
|
for (var i = 0; i < iterations.simple; i++) {
|
|
obj.a = i;
|
|
obj.b = i + 1;
|
|
obj.c = i + 2;
|
|
obj.nested.x = i * 2;
|
|
obj.nested.y = i * 3;
|
|
}
|
|
});
|
|
|
|
return { readTime: readTime, writeTime: writeTime };
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Benchmark: Function Calls
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
function benchFunctionCalls() {
|
|
function add(a, b) { return a + b; }
|
|
function multiply(a, b) { return a * b; }
|
|
function complexCalc(a, b, c) { return (a + b) * c / 2; }
|
|
|
|
var obj = {
|
|
method: function(x) { return x * 2; },
|
|
nested: {
|
|
deepMethod: function(x, y) { return x + y; }
|
|
}
|
|
};
|
|
|
|
var simpleCallTime = measureTime(function() {
|
|
var result = 0;
|
|
for (var i = 0; i < iterations.simple; i++) {
|
|
result = add(i, 1);
|
|
result = multiply(result, 2);
|
|
}
|
|
});
|
|
|
|
var methodCallTime = measureTime(function() {
|
|
var result = 0;
|
|
for (var i = 0; i < iterations.simple; i++) {
|
|
result = obj.method(i);
|
|
result = obj.nested.deepMethod(result, i);
|
|
}
|
|
});
|
|
|
|
var complexCallTime = measureTime(function() {
|
|
var result = 0;
|
|
for (var i = 0; i < iterations.medium; i++) {
|
|
result = complexCalc(i, i + 1, i + 2);
|
|
}
|
|
});
|
|
|
|
return {
|
|
simpleCallTime: simpleCallTime,
|
|
methodCallTime: methodCallTime,
|
|
complexCallTime: complexCallTime
|
|
};
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Benchmark: Array Operations
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
function benchArrayOps() {
|
|
var pushTime = measureTime(function() {
|
|
var arr = [];
|
|
for (var i = 0; i < iterations.medium; i++) {
|
|
arr.push(i);
|
|
}
|
|
});
|
|
|
|
var arr = [];
|
|
for (var i = 0; i < 10000; i++) arr.push(i);
|
|
|
|
var accessTime = measureTime(function() {
|
|
var sum = 0;
|
|
for (var i = 0; i < iterations.medium; i++) {
|
|
sum += arr[i % 10000];
|
|
}
|
|
});
|
|
|
|
var iterateTime = measureTime(function() {
|
|
var sum = 0;
|
|
for (var j = 0; j < 1000; j++) {
|
|
for (var i = 0; i < arr.length; i++) {
|
|
sum += arr[i];
|
|
}
|
|
}
|
|
});
|
|
|
|
return {
|
|
pushTime: pushTime,
|
|
accessTime: accessTime,
|
|
iterateTime: iterateTime
|
|
};
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Benchmark: Object Creation
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
function benchObjectCreation() {
|
|
var literalTime = measureTime(function() {
|
|
for (var i = 0; i < iterations.medium; i++) {
|
|
var obj = { x: i, y: i * 2, z: i * 3 };
|
|
}
|
|
});
|
|
|
|
function Point(x, y) {
|
|
this.x = x;
|
|
this.y = y;
|
|
}
|
|
|
|
var constructorTime = measureTime(function() {
|
|
for (var i = 0; i < iterations.medium; i++) {
|
|
var p = new Point(i, i * 2);
|
|
}
|
|
});
|
|
|
|
var protoObj = {
|
|
x: 0,
|
|
y: 0,
|
|
move: function(dx, dy) {
|
|
this.x += dx;
|
|
this.y += dy;
|
|
}
|
|
};
|
|
|
|
var prototypeTime = measureTime(function() {
|
|
for (var i = 0; i < iterations.medium; i++) {
|
|
var obj = Object.create(protoObj);
|
|
obj.x = i;
|
|
obj.y = i * 2;
|
|
}
|
|
});
|
|
|
|
return {
|
|
literalTime: literalTime,
|
|
constructorTime: constructorTime,
|
|
prototypeTime: prototypeTime
|
|
};
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Benchmark: String Operations
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
function benchStringOps() {
|
|
var concatTime = measureTime(function() {
|
|
var str = "";
|
|
for (var i = 0; i < iterations.complex; i++) {
|
|
str = "test" + i + "value";
|
|
}
|
|
});
|
|
|
|
var strings = [];
|
|
for (var i = 0; i < 1000; i++) {
|
|
strings.push("string" + i);
|
|
}
|
|
|
|
var joinTime = measureTime(function() {
|
|
for (var i = 0; i < iterations.complex; i++) {
|
|
var result = strings.join(",");
|
|
}
|
|
});
|
|
|
|
var splitTime = measureTime(function() {
|
|
var str = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p";
|
|
for (var i = 0; i < iterations.medium; i++) {
|
|
var parts = str.split(",");
|
|
}
|
|
});
|
|
|
|
return {
|
|
concatTime: concatTime,
|
|
joinTime: joinTime,
|
|
splitTime: splitTime
|
|
};
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Benchmark: Arithmetic Operations
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
function benchArithmetic() {
|
|
var intMathTime = measureTime(function() {
|
|
var result = 1;
|
|
for (var i = 0; i < iterations.simple; i++) {
|
|
result = ((result + i) * 2 - 1) / 3;
|
|
result = result % 1000 + 1;
|
|
}
|
|
});
|
|
|
|
var floatMathTime = measureTime(function() {
|
|
var result = 1.5;
|
|
for (var i = 0; i < iterations.simple; i++) {
|
|
result = Math.sin(result) + Math.cos(i * 0.01);
|
|
result = Math.sqrt(Math.abs(result)) + 0.1;
|
|
}
|
|
});
|
|
|
|
var bitwiseTime = measureTime(function() {
|
|
var result = 0;
|
|
for (var i = 0; i < iterations.simple; i++) {
|
|
result = (result ^ i) & 0xFFFF;
|
|
result = (result << 1) | (result >> 15);
|
|
}
|
|
});
|
|
|
|
return {
|
|
intMathTime: intMathTime,
|
|
floatMathTime: floatMathTime,
|
|
bitwiseTime: bitwiseTime
|
|
};
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Benchmark: Closure Operations
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
function benchClosures() {
|
|
function makeAdder(x) {
|
|
return function(y) { return x + y; };
|
|
}
|
|
|
|
var closureCreateTime = measureTime(function() {
|
|
var funcs = [];
|
|
for (var i = 0; i < iterations.medium; i++) {
|
|
funcs.push(makeAdder(i));
|
|
}
|
|
});
|
|
|
|
var adders = [];
|
|
for (var i = 0; i < 1000; i++) {
|
|
adders.push(makeAdder(i));
|
|
}
|
|
|
|
var closureCallTime = measureTime(function() {
|
|
var sum = 0;
|
|
for (var i = 0; i < iterations.medium; i++) {
|
|
sum += adders[i % 1000](i);
|
|
}
|
|
});
|
|
|
|
return {
|
|
closureCreateTime: closureCreateTime,
|
|
closureCallTime: closureCallTime
|
|
};
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Main benchmark runner
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
log.console("JavaScript Performance Benchmark");
|
|
log.console("================================\n");
|
|
|
|
// Property Access
|
|
log.console("BENCHMARK: Property Access");
|
|
var propResults = benchPropertyAccess();
|
|
log.console(" Read time: " + propResults.readTime.toFixed(3) + "s => " +
|
|
(iterations.simple / propResults.readTime).toFixed(1) + " reads/sec [" +
|
|
(propResults.readTime / iterations.simple * 1e9).toFixed(1) + " ns/op]");
|
|
log.console(" Write time: " + propResults.writeTime.toFixed(3) + "s => " +
|
|
(iterations.simple / propResults.writeTime).toFixed(1) + " writes/sec [" +
|
|
(propResults.writeTime / iterations.simple * 1e9).toFixed(1) + " ns/op]");
|
|
log.console("");
|
|
|
|
// Function Calls
|
|
log.console("BENCHMARK: Function Calls");
|
|
var funcResults = benchFunctionCalls();
|
|
log.console(" Simple calls: " + funcResults.simpleCallTime.toFixed(3) + "s => " +
|
|
(iterations.simple / funcResults.simpleCallTime).toFixed(1) + " calls/sec [" +
|
|
(funcResults.simpleCallTime / iterations.simple * 1e9).toFixed(1) + " ns/op]");
|
|
log.console(" Method calls: " + funcResults.methodCallTime.toFixed(3) + "s => " +
|
|
(iterations.simple / funcResults.methodCallTime).toFixed(1) + " calls/sec [" +
|
|
(funcResults.methodCallTime / iterations.simple * 1e9).toFixed(1) + " ns/op]");
|
|
log.console(" Complex calls: " + funcResults.complexCallTime.toFixed(3) + "s => " +
|
|
(iterations.medium / funcResults.complexCallTime).toFixed(1) + " calls/sec [" +
|
|
(funcResults.complexCallTime / iterations.medium * 1e9).toFixed(1) + " ns/op]");
|
|
log.console("");
|
|
|
|
// Array Operations
|
|
log.console("BENCHMARK: Array Operations");
|
|
var arrayResults = benchArrayOps();
|
|
log.console(" Push: " + arrayResults.pushTime.toFixed(3) + "s => " +
|
|
(iterations.medium / arrayResults.pushTime).toFixed(1) + " pushes/sec [" +
|
|
(arrayResults.pushTime / iterations.medium * 1e9).toFixed(1) + " ns/op]");
|
|
log.console(" Access: " + arrayResults.accessTime.toFixed(3) + "s => " +
|
|
(iterations.medium / arrayResults.accessTime).toFixed(1) + " accesses/sec [" +
|
|
(arrayResults.accessTime / iterations.medium * 1e9).toFixed(1) + " ns/op]");
|
|
log.console(" Iterate: " + arrayResults.iterateTime.toFixed(3) + "s => " +
|
|
(1000 / arrayResults.iterateTime).toFixed(1) + " full iterations/sec");
|
|
log.console("");
|
|
|
|
// Object Creation
|
|
log.console("BENCHMARK: Object Creation");
|
|
var objResults = benchObjectCreation();
|
|
log.console(" Literal: " + objResults.literalTime.toFixed(3) + "s => " +
|
|
(iterations.medium / objResults.literalTime).toFixed(1) + " creates/sec [" +
|
|
(objResults.literalTime / iterations.medium * 1e9).toFixed(1) + " ns/op]");
|
|
log.console(" Constructor: " + objResults.constructorTime.toFixed(3) + "s => " +
|
|
(iterations.medium / objResults.constructorTime).toFixed(1) + " creates/sec [" +
|
|
(objResults.constructorTime / iterations.medium * 1e9).toFixed(1) + " ns/op]");
|
|
log.console(" Prototype: " + objResults.prototypeTime.toFixed(3) + "s => " +
|
|
(iterations.medium / objResults.prototypeTime).toFixed(1) + " creates/sec [" +
|
|
(objResults.prototypeTime / iterations.medium * 1e9).toFixed(1) + " ns/op]");
|
|
log.console("");
|
|
|
|
// String Operations
|
|
log.console("BENCHMARK: String Operations");
|
|
var strResults = benchStringOps();
|
|
log.console(" Concat: " + strResults.concatTime.toFixed(3) + "s => " +
|
|
(iterations.complex / strResults.concatTime).toFixed(1) + " concats/sec [" +
|
|
(strResults.concatTime / iterations.complex * 1e9).toFixed(1) + " ns/op]");
|
|
log.console(" Join: " + strResults.joinTime.toFixed(3) + "s => " +
|
|
(iterations.complex / strResults.joinTime).toFixed(1) + " joins/sec [" +
|
|
(strResults.joinTime / iterations.complex * 1e9).toFixed(1) + " ns/op]");
|
|
log.console(" Split: " + strResults.splitTime.toFixed(3) + "s => " +
|
|
(iterations.medium / strResults.splitTime).toFixed(1) + " splits/sec [" +
|
|
(strResults.splitTime / iterations.medium * 1e9).toFixed(1) + " ns/op]");
|
|
log.console("");
|
|
|
|
// Arithmetic Operations
|
|
log.console("BENCHMARK: Arithmetic Operations");
|
|
var mathResults = benchArithmetic();
|
|
log.console(" Integer math: " + mathResults.intMathTime.toFixed(3) + "s => " +
|
|
(iterations.simple / mathResults.intMathTime).toFixed(1) + " ops/sec [" +
|
|
(mathResults.intMathTime / iterations.simple * 1e9).toFixed(1) + " ns/op]");
|
|
log.console(" Float math: " + mathResults.floatMathTime.toFixed(3) + "s => " +
|
|
(iterations.simple / mathResults.floatMathTime).toFixed(1) + " ops/sec [" +
|
|
(mathResults.floatMathTime / iterations.simple * 1e9).toFixed(1) + " ns/op]");
|
|
log.console(" Bitwise: " + mathResults.bitwiseTime.toFixed(3) + "s => " +
|
|
(iterations.simple / mathResults.bitwiseTime).toFixed(1) + " ops/sec [" +
|
|
(mathResults.bitwiseTime / iterations.simple * 1e9).toFixed(1) + " ns/op]");
|
|
log.console("");
|
|
|
|
// Closures
|
|
log.console("BENCHMARK: Closures");
|
|
var closureResults = benchClosures();
|
|
log.console(" Create: " + closureResults.closureCreateTime.toFixed(3) + "s => " +
|
|
(iterations.medium / closureResults.closureCreateTime).toFixed(1) + " creates/sec [" +
|
|
(closureResults.closureCreateTime / iterations.medium * 1e9).toFixed(1) + " ns/op]");
|
|
log.console(" Call: " + closureResults.closureCallTime.toFixed(3) + "s => " +
|
|
(iterations.medium / closureResults.closureCallTime).toFixed(1) + " calls/sec [" +
|
|
(closureResults.closureCallTime / iterations.medium * 1e9).toFixed(1) + " ns/op]");
|
|
log.console("");
|
|
|
|
log.console("---------------------------------------------------------");
|
|
log.console("Benchmark complete.\n");
|
|
|
|
$_.stop()
|