committed by
GitHub
2 changed files with 124 additions and 114 deletions
@ -1,151 +1,161 @@ |
|||||
/** |
/** |
||||
* Adaptive benchmarking. Starts with `initialTimes` iterations, increasing by |
* Adaptive benchmarking. Starts with `initialTimes` iterations, increasing by |
||||
* a power of two each time until the benchmark takes at least `minDuration_ms` |
* a power of two each time until the benchmark takes at least `minDurationMs` |
||||
* milliseconds to complete. |
* milliseconds to complete. |
||||
*/ |
*/ |
||||
|
|
||||
var Canvas = require('../lib/canvas') |
var Canvas = require('../') |
||||
, canvas = new Canvas(200, 200) |
var canvas = new Canvas(200, 200) |
||||
, largeCanvas = new Canvas(1000, 1000) |
var largeCanvas = new Canvas(1000, 1000) |
||||
, ctx = canvas.getContext('2d'); |
var ctx = canvas.getContext('2d') |
||||
|
|
||||
var initialTimes = 10; |
var initialTimes = 10 |
||||
var minDuration_ms = 2000; |
var minDurationMs = 2000 |
||||
|
|
||||
var queue = [], running = false; |
var queue = [] |
||||
|
var running = false |
||||
|
|
||||
function bm(label, fn) { |
function bm (label, fn) { |
||||
queue.push({label: label, fn: fn}); |
queue.push({ label: label, fn: fn }) |
||||
next(); |
next() |
||||
} |
} |
||||
|
|
||||
function next() { |
function next () { |
||||
if (queue.length && !running) { |
if (queue.length && !running) { |
||||
run(queue.pop(), initialTimes, Date.now()); |
run(queue.pop(), initialTimes, Date.now()) |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
function run(benchmark, n, start) { |
function run (benchmark, n, start) { |
||||
running = true; |
running = true |
||||
var originalN = n; |
var originalN = n |
||||
var fn = benchmark.fn; |
var fn = benchmark.fn |
||||
|
|
||||
if (fn.length) { // async
|
if (fn.length) { // async
|
||||
var pending = n; |
var pending = n |
||||
while (n--) fn(function () { |
|
||||
--pending || done(benchmark, originalN, start, true); |
while (n--) { |
||||
}); |
fn(function () { |
||||
|
--pending || done(benchmark, originalN, start, true) |
||||
|
}) |
||||
|
} |
||||
} else { |
} else { |
||||
while (n--) fn(); |
while (n--) fn() |
||||
done(benchmark, originalN, start); |
done(benchmark, originalN, start) |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
function done(benchmark, times, start, async) { |
function done (benchmark, times, start, isAsync) { |
||||
var duration = Date.now() - start; |
var duration = Date.now() - start |
||||
if (duration < minDuration_ms) { |
|
||||
run(benchmark, times * 2, Date.now()); |
if (duration < minDurationMs) { |
||||
|
run(benchmark, times * 2, Date.now()) |
||||
} else { |
} else { |
||||
var opsSec = times / duration * 1000 |
var opsSec = times / duration * 1000 |
||||
if (async) { |
if (isAsync) { |
||||
console.log(' - \x1b[33m%s\x1b[0m %s ops/sec (%s times, async)', benchmark.label, opsSec.toLocaleString(), times); |
console.log(' - \x1b[33m%s\x1b[0m %s ops/sec (%s times, async)', benchmark.label, opsSec.toLocaleString(), times) |
||||
} else { |
} else { |
||||
console.log(' - \x1b[33m%s\x1b[0m %s ops/sec (%s times)', benchmark.label, opsSec.toLocaleString(), times); |
console.log(' - \x1b[33m%s\x1b[0m %s ops/sec (%s times)', benchmark.label, opsSec.toLocaleString(), times) |
||||
} |
} |
||||
running = false; |
running = false |
||||
next(); |
next() |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
// node-canvas
|
// node-canvas
|
||||
|
|
||||
bm('lineTo()', function(){ |
bm('lineTo()', function () { |
||||
ctx.lineTo(0, 50); |
ctx.lineTo(0, 50) |
||||
}); |
}) |
||||
|
|
||||
bm('arc()', function(){ |
bm('arc()', function () { |
||||
ctx.arc(75,75,50,0,Math.PI*2,true); |
ctx.arc(75, 75, 50, 0, Math.PI * 2, true) |
||||
}); |
}) |
||||
|
|
||||
bm('fillStyle= hex', function(){ |
bm('fillStyle= hex', function () { |
||||
ctx.fillStyle = '#FFCCAA'; |
ctx.fillStyle = '#FFCCAA' |
||||
}); |
}) |
||||
|
|
||||
bm('fillStyle= rgba()', function(){ |
bm('fillStyle= rgba()', function () { |
||||
ctx.fillStyle = 'rgba(0,255,80,1)'; |
ctx.fillStyle = 'rgba(0,255,80,1)' |
||||
}); |
}) |
||||
|
|
||||
// Apparently there's a bug in cairo by which the fillRect and strokeRect are
|
// Apparently there's a bug in cairo by which the fillRect and strokeRect are
|
||||
// slow only after a ton of arcs have been drawn.
|
// slow only after a ton of arcs have been drawn.
|
||||
bm('fillRect()', function(){ |
bm('fillRect()', function () { |
||||
ctx.fillRect(50, 50, 100, 100); |
ctx.fillRect(50, 50, 100, 100) |
||||
}); |
}) |
||||
|
|
||||
bm('strokeRect()', function(){ |
bm('strokeRect()', function () { |
||||
ctx.strokeRect(50, 50, 100, 100); |
ctx.strokeRect(50, 50, 100, 100) |
||||
}); |
}) |
||||
|
|
||||
bm('linear gradients', function(){ |
bm('linear gradients', function () { |
||||
var lingrad = ctx.createLinearGradient(0,50,0,95); |
var lingrad = ctx.createLinearGradient(0, 50, 0, 95) |
||||
lingrad.addColorStop(0.5, '#000'); |
lingrad.addColorStop(0.5, '#000') |
||||
lingrad.addColorStop(1, 'rgba(0,0,0,0)'); |
lingrad.addColorStop(1, 'rgba(0,0,0,0)') |
||||
ctx.fillStyle = lingrad; |
ctx.fillStyle = lingrad |
||||
ctx.fillRect(10,10,130,130); |
ctx.fillRect(10, 10, 130, 130) |
||||
}); |
}) |
||||
|
|
||||
bm('toBuffer() 200x200', function(){ |
bm('toBuffer() 200x200', function () { |
||||
canvas.toBuffer(); |
canvas.toBuffer() |
||||
}); |
}) |
||||
|
|
||||
bm('toBuffer() 1000x1000', function(){ |
bm('toBuffer() 1000x1000', function () { |
||||
largeCanvas.toBuffer(); |
largeCanvas.toBuffer() |
||||
}); |
}) |
||||
|
|
||||
bm('toBuffer() async 200x200', function(done){ |
bm('toBuffer() async 200x200', function (done) { |
||||
canvas.toBuffer(function (err, buf) { |
canvas.toBuffer(function (err, buf) { |
||||
done(); |
if (err) throw err |
||||
}); |
|
||||
}); |
done() |
||||
|
}) |
||||
|
}) |
||||
|
|
||||
bm('toBuffer() async 1000x1000', function(done){ |
bm('toBuffer() async 1000x1000', function (done) { |
||||
largeCanvas.toBuffer(function (err, buf) { |
largeCanvas.toBuffer(function (err, buf) { |
||||
done(); |
if (err) throw err |
||||
}); |
|
||||
}); |
done() |
||||
|
}) |
||||
bm('toBuffer().toString("base64") 200x200', function(){ |
}) |
||||
canvas.toBuffer().toString('base64'); |
|
||||
}); |
bm('toBuffer().toString("base64") 200x200', function () { |
||||
|
canvas.toBuffer().toString('base64') |
||||
bm('toDataURL() 200x200', function(){ |
}) |
||||
canvas.toDataURL(); |
|
||||
}); |
bm('toDataURL() 200x200', function () { |
||||
|
canvas.toDataURL() |
||||
bm('moveTo() / arc() / stroke()', function(){ |
}) |
||||
ctx.beginPath(); |
|
||||
ctx.arc(75,75,50,0,Math.PI*2,true); // Outer circle
|
bm('moveTo() / arc() / stroke()', function () { |
||||
ctx.moveTo(110,75); |
ctx.beginPath() |
||||
ctx.arc(75,75,35,0,Math.PI,false); // Mouth
|
ctx.arc(75, 75, 50, 0, Math.PI * 2, true) // Outer circle
|
||||
ctx.moveTo(65,65); |
ctx.moveTo(110, 75) |
||||
ctx.arc(60,65,5,0,Math.PI*2,true); // Left eye
|
ctx.arc(75, 75, 35, 0, Math.PI, false) // Mouth
|
||||
ctx.moveTo(95,65); |
ctx.moveTo(65, 65) |
||||
ctx.arc(90,65,5,0,Math.PI*2,true); // Right eye
|
ctx.arc(60, 65, 5, 0, Math.PI * 2, true) // Left eye
|
||||
ctx.stroke(); |
ctx.moveTo(95, 65) |
||||
}); |
ctx.arc(90, 65, 5, 0, Math.PI * 2, true) // Right eye
|
||||
|
ctx.stroke() |
||||
bm('createImageData(300,300)', function(){ |
}) |
||||
ctx.createImageData(300,300); |
|
||||
}); |
bm('createImageData(300,300)', function () { |
||||
|
ctx.createImageData(300, 300) |
||||
bm('getImageData(0,0,100,100)', function(){ |
}) |
||||
ctx.getImageData(0,0,100,100); |
|
||||
}); |
bm('getImageData(0,0,100,100)', function () { |
||||
|
ctx.getImageData(0, 0, 100, 100) |
||||
bm('PNGStream 200x200', function(done){ |
}) |
||||
var stream = canvas.createSyncPNGStream(); |
|
||||
stream.on('data', function(chunk){ |
bm('PNGStream 200x200', function (done) { |
||||
|
var stream = canvas.createSyncPNGStream() |
||||
|
stream.on('data', function (chunk) { |
||||
// whatever
|
// whatever
|
||||
}); |
}) |
||||
stream.on('end', function(){ |
stream.on('end', function () { |
||||
done(); |
done() |
||||
}); |
}) |
||||
}); |
}) |
||||
|
Loading…
Reference in new issue