Skip to content

Commit

Permalink
Additional benchmarks (#45)
Browse files Browse the repository at this point in the history
* Add growth benchmarks

- growth: Starts with a fresh queue pushing and shifting elements.
- This should at least partially test the buffer growth and
  re-alignment performance

* Add toArray benchmark

- toArray: Simply benchmark call the toArray function on the queue
  in different states
- State "head at 0": The head is at buffer index 0. This occurs when
  only adding / popping but never shifting or after a growth
- State "non-contiguous": The buffer is wrapped (head > tail). This
  occurs when adding and shifting until the tail reaches the capacity.
  In this case the buffer has to be copied in 2 steps
- State "non zero head": The buffer head is not at index 0, but still <
  tail. This means the content is still contiguous and can be copied in
  one move

* Add fromArray benchmark
  • Loading branch information
dnlmlr authored Jul 16, 2022
1 parent f400043 commit 0f4193e
Show file tree
Hide file tree
Showing 4 changed files with 176 additions and 1 deletion.
29 changes: 29 additions & 0 deletions benchmark/fromArray.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
'use strict';

require('./print');

var Benchmark = require('benchmark');
var suite = new Benchmark.Suite();

var Denque = require('./../');
var DoubleEndedQueue = require('double-ended-queue');

var l = 100000;

var baseArray = new Array(l);

while (--l) {
baseArray.push(l);
}

suite
.add('denque', function () {
var queue = new Denque(baseArray);
})
.add('double-ended-queue', function () {
var queue = new DoubleEndedQueue(baseArray);
})
.on('cycle', function (e) {
console.log('' + e.target);
})
.run();
33 changes: 33 additions & 0 deletions benchmark/growth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
'use strict';

require('./print');

var Benchmark = require('benchmark');
var suite = new Benchmark.Suite();

var Denque = require('./../');
var DoubleEndedQueue = require('double-ended-queue');

var n = 1000;

suite
.add('denque', function () {
var denque = new Denque();

for (var i = 0; i < n; i++) denque.push(i);
for (var i = 0; i < n / 2; i++) denque.shift();
for (var i = 0; i < n; i++) denque.push(i);
for (var i = 0; i < n + n / 2; i++) denque.shift();
})
.add('double-ended-queue', function () {
var doubleEndedQueue = new DoubleEndedQueue();

for (var i = 0; i < n; i++) doubleEndedQueue.push(i);
for (var i = 0; i < n / 2; i++) doubleEndedQueue.shift();
for (var i = 0; i < n; i++) doubleEndedQueue.push(i);
for (var i = 0; i < n + n / 2; i++) doubleEndedQueue.shift();
})
.on('cycle', function (e) {
console.log('' + e.target);
})
.run();
110 changes: 110 additions & 0 deletions benchmark/toArray.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
'use strict';

require('./print');

var Benchmark = require('benchmark');
var suite = new Benchmark.Suite();

var Denque = require('./../');
var DoubleEndedQueue = require('double-ended-queue');

var denque = new Denque();
var denque_NonContiguous = new Denque();
var denque_NonZeroHead = new Denque();

var doubleEndedQueue = new DoubleEndedQueue();
var doubleEndedQueue_NonContiguous = new DoubleEndedQueue();
var doubleEndedQueue_NonZeroHead = new DoubleEndedQueue();

var array = new Array();


// Number of elements has to be 1 less than a power of 2 in order to ensure that the buffer
// wrapping occurs on the _NonContiguous variant and not the base variant
var l = (1 << 21) - 1;
var l_half = (l / 2) >> 0;


for (var i = 0; i < l; i++) {
denque.push(i);
denque_NonContiguous.push(i);
denque_NonZeroHead.push(i);

doubleEndedQueue.push(i);
doubleEndedQueue_NonContiguous.push(i);
doubleEndedQueue_NonZeroHead.push(i);

array.push(i)
}

for (var i = 0; i < l_half; i++) {
denque_NonZeroHead.push(i);
doubleEndedQueue_NonZeroHead.push(i);
}

// Shift half and push half. This should make the internal buffer non contiguous and about half
// before and half after the wrap
for (var i = 0; i < l_half; i++) {
denque_NonContiguous.shift();
denque_NonContiguous.push(i);

doubleEndedQueue_NonContiguous.shift();
doubleEndedQueue_NonContiguous.push(i);

denque_NonZeroHead.shift();
doubleEndedQueue_NonZeroHead.shift();
}

// Make sure that the denqueue buffer is contiguous or not
console.assert(denque._head < denque._tail, "Denque (contiguous) buffer is not contiguous");
console.assert(
denque_NonZeroHead._head < denque_NonZeroHead._tail,
"Denque (non zero head) buffer is not contiguous"
);
console.assert(
denque_NonContiguous._head > denque_NonContiguous._tail,
"Denque (non-contiguous) buffer is contiguous"
);

// Make sure that the same number of elements is used in each queue, despite shifts
console.assert(denque.length == denque_NonContiguous.length, "Denque variant length missmatch");
console.assert(denque.length == denque_NonZeroHead.length, "Denque variant length missmatch");
console.assert(denque.length == doubleEndedQueue.length, "Denque vs double-ended-queue length missmatch");
console.assert(doubleEndedQueue.length == doubleEndedQueue_NonContiguous.length, "Denque variant length missmatch");
console.assert(doubleEndedQueue.length == doubleEndedQueue_NonZeroHead.length, "Denque variant length missmatch");


suite
.add('denque (head at 0)', function () {
var arr = denque.toArray();
})
.add('double-ended-queue (head at 0)', function () {
var arr = doubleEndedQueue.toArray();
})
.add('denque (non-contiguous)', function () {
var arr = denque_NonContiguous.toArray();
})
.add('double-ended-queue (non-contiguous)', function () {
var arr = doubleEndedQueue_NonContiguous.toArray();
})
.add('denque (non zero head)', function () {
var arr = denque_NonZeroHead.toArray();
})
.add('double-ended-queue (non zero head)', function () {
var arr = doubleEndedQueue_NonZeroHead.toArray();
})
.add('array copy (prealloc + for loop)', function () {
var arr = new Array(array.length);
for (var i = 0; i < array.length; i++) arr[i] = array[i];
})
.add('array copy (no prealloc + for loop)', function () {
var arr = new Array();
for (var i = 0; i < array.length; i++) arr.push(array[i]);
})
.add('array copy (slice)', function () {
var arr = array.slice(0, array.length);
})
.on('cycle', function (e) {
console.log('' + e.target);
})
.run();
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@
"benchmark_2mil": "node benchmark/two_million",
"benchmark_splice": "node benchmark/splice",
"benchmark_remove": "node benchmark/remove",
"benchmark_removeOne": "node benchmark/removeOne"
"benchmark_removeOne": "node benchmark/removeOne",
"benchmark_growth": "node benchmark/growth",
"benchmark_toArray": "node benchmark/toArray",
"benchmark_fromArray": "node benchmark/fromArray"
},
"repository": {
"type": "git",
Expand Down

0 comments on commit 0f4193e

Please sign in to comment.