miner: use a proper priority queue.
This commit is contained in:
parent
2b6b985388
commit
70d4de39ce
@ -10,6 +10,7 @@
|
||||
var assert = require('assert');
|
||||
var util = require('../utils/util');
|
||||
var co = require('../utils/co');
|
||||
var Heap = require('../utils/heap');
|
||||
var AsyncObject = require('../utils/asyncobject');
|
||||
var Address = require('../primitives/address');
|
||||
var MinerBlock = require('./minerblock');
|
||||
@ -368,7 +369,7 @@ Miner.prototype.getAddress = function getAddress() {
|
||||
Miner.prototype.build = function build(attempt) {
|
||||
var depMap = {};
|
||||
var block = attempt.block;
|
||||
var queue = new Queue(cmpRate);
|
||||
var queue = new Heap(cmpRate);
|
||||
var priority = this.priorityWeight > 0;
|
||||
var i, j, entry, item, tx, hash, input;
|
||||
var prev, deps, hashes, weight, sigops;
|
||||
@ -438,7 +439,7 @@ Miner.prototype.build = function build(attempt) {
|
||||
if (weight > this.options.priorityWeight
|
||||
|| item.priority < this.options.priorityThreshold) {
|
||||
queue.set(cmpRate);
|
||||
queue.sort();
|
||||
queue.init();
|
||||
priority = false;
|
||||
queue.push(item);
|
||||
continue;
|
||||
@ -615,45 +616,6 @@ MinerOptions.fromOptions = function fromOptions(options) {
|
||||
return new MinerOptions().fromOptions(options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Queue
|
||||
* @constructor
|
||||
* @ignore
|
||||
*/
|
||||
|
||||
function Queue(cmp) {
|
||||
if (!(this instanceof Queue))
|
||||
return new Queue(cmp);
|
||||
|
||||
this.cmp = null;
|
||||
this.items = [];
|
||||
this.set(cmp);
|
||||
}
|
||||
|
||||
Queue.prototype.size = function size() {
|
||||
return this.items.length;
|
||||
};
|
||||
|
||||
Queue.prototype.push = function push(item) {
|
||||
assert(this.cmp, 'No comparator for queue.');
|
||||
util.binaryInsert(this.items, item, this.cmp);
|
||||
};
|
||||
|
||||
Queue.prototype.pop = function pop() {
|
||||
return this.items.pop();
|
||||
};
|
||||
|
||||
Queue.prototype.set = function set(cmp) {
|
||||
assert(cmp == null || typeof cmp === 'function',
|
||||
'Comparator must be a function.');
|
||||
this.cmp = cmp || null;
|
||||
};
|
||||
|
||||
Queue.prototype.sort = function sort() {
|
||||
assert(this.cmp, 'No comparator for queue.');
|
||||
this.items.sort(this.cmp);
|
||||
};
|
||||
|
||||
/*
|
||||
* Helpers
|
||||
*/
|
||||
|
||||
235
lib/utils/heap.js
Normal file
235
lib/utils/heap.js
Normal file
@ -0,0 +1,235 @@
|
||||
/*!
|
||||
* heap.js - heap object for bcoin
|
||||
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
|
||||
/**
|
||||
* Priority Queue
|
||||
* @alias module:utils.Heap
|
||||
* @constructor
|
||||
* @param {Function?} cmp
|
||||
*/
|
||||
|
||||
function Heap(cmp) {
|
||||
if (!(this instanceof Heap))
|
||||
return new Heap(cmp);
|
||||
|
||||
this.cmp = null;
|
||||
this.items = [];
|
||||
this.set(cmp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize and sort heap.
|
||||
*/
|
||||
|
||||
Heap.prototype.init = function init() {
|
||||
var n = this.items.length;
|
||||
var i;
|
||||
|
||||
if (n <= 1)
|
||||
return;
|
||||
|
||||
for (i = (n / 2 | 0) - 1; i >= 0; i--)
|
||||
this.down(i, n);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get heap size.
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
Heap.prototype.size = function size() {
|
||||
return this.items.length;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set comparator.
|
||||
* @param {Function} cmp
|
||||
*/
|
||||
|
||||
Heap.prototype.set = function set(cmp) {
|
||||
assert(cmp == null || typeof cmp === 'function',
|
||||
'Comparator must be a function.');
|
||||
this.cmp = cmp || null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Push item onto heap.
|
||||
* @param {Object} item
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
Heap.prototype.push = function push(item) {
|
||||
this.items.push(item);
|
||||
this.up(this.items.length - 1);
|
||||
return this.items.length;
|
||||
};
|
||||
|
||||
/**
|
||||
* Pop next item off of heap.
|
||||
* @param {Object} item
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
Heap.prototype.pop = function pop(item) {
|
||||
var n;
|
||||
|
||||
if (this.items.length === 0)
|
||||
return;
|
||||
|
||||
n = this.items.length - 1;
|
||||
|
||||
this.swap(0, n);
|
||||
this.down(0, n);
|
||||
|
||||
return this.items.pop();
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove item from heap.
|
||||
* @param {Number} i
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
Heap.prototype.remove = function remove(i) {
|
||||
var n;
|
||||
|
||||
if (this.items.length === 0)
|
||||
return;
|
||||
|
||||
n = this.items.length - 1;
|
||||
|
||||
if (n !== i) {
|
||||
this.swap(i, n);
|
||||
this.down(i, n);
|
||||
this.up(i);
|
||||
}
|
||||
|
||||
return this.items.pop();
|
||||
};
|
||||
|
||||
/**
|
||||
* Swap indicies.
|
||||
* @private
|
||||
* @param {Number} a
|
||||
* @param {Number} b
|
||||
*/
|
||||
|
||||
Heap.prototype.swap = function swap(a, b) {
|
||||
var x = this.items[a];
|
||||
var y = this.items[b];
|
||||
this.items[a] = y;
|
||||
this.items[b] = x;
|
||||
};
|
||||
|
||||
/**
|
||||
* Compare indicies.
|
||||
* @private
|
||||
* @param {Number} i
|
||||
* @param {Number} j
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
Heap.prototype.less = function less(i, j) {
|
||||
return this.cmp(this.items[i], this.items[j]) >= 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Bubble item down.
|
||||
* @private
|
||||
* @param {Number} i
|
||||
* @param {Number} n
|
||||
*/
|
||||
|
||||
Heap.prototype.down = function down(i, n) {
|
||||
var j, l, r;
|
||||
|
||||
for (;;) {
|
||||
l = 2 * i + 1;
|
||||
|
||||
assert(l >= 0);
|
||||
|
||||
if (l < 0 || l >= n)
|
||||
break;
|
||||
|
||||
j = l;
|
||||
r = l + 1;
|
||||
|
||||
if (r < n && !this.less(l, r))
|
||||
j = r;
|
||||
|
||||
if (!this.less(j, i))
|
||||
break;
|
||||
|
||||
this.swap(i, j);
|
||||
i = j;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Bubble item up.
|
||||
* @private
|
||||
* @param {Number} i
|
||||
*/
|
||||
|
||||
Heap.prototype.up = function up(i) {
|
||||
var j;
|
||||
|
||||
for (;;) {
|
||||
j = (i - 1) / 2 | 0;
|
||||
|
||||
assert(j >= 0);
|
||||
|
||||
if (j < 0 || j === i)
|
||||
break;
|
||||
|
||||
if (!this.less(i, j))
|
||||
break;
|
||||
|
||||
this.swap(j, i);
|
||||
i = j;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert heap to sorted array.
|
||||
* @returns {Object[]}
|
||||
*/
|
||||
|
||||
Heap.prototype.toArray = function toArray() {
|
||||
var heap = new Heap(this.cmp);
|
||||
var result = [];
|
||||
|
||||
heap.items = this.items.slice();
|
||||
|
||||
while (heap.size() > 0)
|
||||
result.push(heap.pop());
|
||||
|
||||
return result.reverse();
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiate heap from array and comparator.
|
||||
* @param {Function} cmp
|
||||
* @param {Object[]} items
|
||||
* @returns {Heap}
|
||||
*/
|
||||
|
||||
Heap.fromArray = function fromArray(cmp, items) {
|
||||
var heap = new Heap(cmp);
|
||||
heap.items = items;
|
||||
heap.init();
|
||||
return heap;
|
||||
};
|
||||
|
||||
/*
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = Heap;
|
||||
Loading…
Reference in New Issue
Block a user