Browse Source

more playing with mempool summary data

It's not "done", but it probably never will be. I'm satisfied to consider this: Fixes #28
fix-133-memory-crash
Dan Janosik 6 years ago
parent
commit
3a251e3cf2
  1. 80
      app/api/coreApi.js
  2. 81
      views/mempool-summary.pug

80
app/api/coreApi.js

@ -153,10 +153,16 @@ function getMempoolStats() {
tryCacheThenRpcApi(miscCache, "getRawMempool", 5000, rpcApi.getRawMempool).then(function(result) { tryCacheThenRpcApi(miscCache, "getRawMempool", 5000, rpcApi.getRawMempool).then(function(result) {
var maxFee = 0; var maxFee = 0;
var maxFeePerByte = 0; var maxFeePerByte = 0;
var maxAge = 0;
var maxSize = 0;
var ages = [];
var sizes = [];
for (var txid in result) { for (var txid in result) {
var txMempoolInfo = result[txid]; var txMempoolInfo = result[txid];
var fee = txMempoolInfo.modifiedfee; var fee = txMempoolInfo.modifiedfee;
var feePerByte = txMempoolInfo.modifiedfee / txMempoolInfo.size; var feePerByte = txMempoolInfo.modifiedfee / txMempoolInfo.size;
var age = Date.now() / 1000 - txMempoolInfo.time;
var size = txMempoolInfo.size;
if (fee > maxFee) { if (fee > maxFee) {
maxFee = txMempoolInfo.modifiedfee; maxFee = txMempoolInfo.modifiedfee;
@ -165,8 +171,39 @@ function getMempoolStats() {
if (feePerByte > maxFeePerByte) { if (feePerByte > maxFeePerByte) {
maxFeePerByte = txMempoolInfo.modifiedfee / txMempoolInfo.size; maxFeePerByte = txMempoolInfo.modifiedfee / txMempoolInfo.size;
} }
ages.push({age:age, txid:txid});
sizes.push({size:size, txid:txid});
if (age > maxAge) {
maxAge = age;
}
if (size > maxSize) {
maxSize = size;
}
} }
ages.sort(function(a, b) {
if (a.age != b.age) {
return b.age - a.age;
} else {
return a.txid.localeCompare(b.txid);
}
});
sizes.sort(function(a, b) {
if (a.size != b.size) {
return b.size - a.size;
} else {
return a.txid.localeCompare(b.txid);
}
});
maxSize = 4000;
var satoshiPerByteBucketMaxima = coins[config.coin].feeSatoshiPerByteBucketMaxima; var satoshiPerByteBucketMaxima = coins[config.coin].feeSatoshiPerByteBucketMaxima;
var bucketCount = satoshiPerByteBucketMaxima.length + 1; var bucketCount = satoshiPerByteBucketMaxima.length + 1;
@ -182,6 +219,30 @@ function getMempoolStats() {
} }
} }
var ageBucketCount = 100;
var ageBucketTxCounts = [];
var ageBucketLabels = [];
var sizeBucketCount = 100;
var sizeBucketTxCounts = [];
var sizeBucketLabels = [];
for (var i = 0; i < ageBucketCount; i++) {
ageBucketTxCounts.push(0);
ageBucketLabels.push(parseInt(i * maxAge / 10) + " - " + parseInt((i + 1) * maxAge / 10));
}
for (var i = 0; i < sizeBucketCount; i++) {
sizeBucketTxCounts.push(0);
if (i == sizeBucketCount - 1) {
sizeBucketLabels.push(parseInt(i * maxSize / 10) + "+");
} else {
sizeBucketLabels.push(parseInt(i * maxSize / 10) + " - " + parseInt((i + 1) * maxSize / 10));
}
}
satoshiPerByteBucketLabels[bucketCount - 1] = (satoshiPerByteBucketMaxima[satoshiPerByteBucketMaxima.length - 1] + "+"); satoshiPerByteBucketLabels[bucketCount - 1] = (satoshiPerByteBucketMaxima[satoshiPerByteBucketMaxima.length - 1] + "+");
var summary = { var summary = {
@ -189,7 +250,11 @@ function getMempoolStats() {
"totalFees":0, "totalFees":0,
"totalBytes":0, "totalBytes":0,
"satoshiPerByteBuckets":satoshiPerByteBuckets, "satoshiPerByteBuckets":satoshiPerByteBuckets,
"satoshiPerByteBucketLabels":satoshiPerByteBucketLabels "satoshiPerByteBucketLabels":satoshiPerByteBucketLabels,
"ageBucketTxCounts":ageBucketTxCounts,
"ageBucketLabels":ageBucketLabels,
"sizeBucketTxCounts":sizeBucketTxCounts,
"sizeBucketLabels":sizeBucketLabels
}; };
for (var txid in result) { for (var txid in result) {
@ -197,6 +262,8 @@ function getMempoolStats() {
var fee = txMempoolInfo.modifiedfee; var fee = txMempoolInfo.modifiedfee;
var feePerByte = txMempoolInfo.modifiedfee / txMempoolInfo.size; var feePerByte = txMempoolInfo.modifiedfee / txMempoolInfo.size;
var satoshiPerByte = feePerByte * 100000000; var satoshiPerByte = feePerByte * 100000000;
var age = Date.now() / 1000 - txMempoolInfo.time;
var size = txMempoolInfo.size;
var addedToBucket = false; var addedToBucket = false;
for (var i = 0; i < satoshiPerByteBucketMaxima.length; i++) { for (var i = 0; i < satoshiPerByteBucketMaxima.length; i++) {
@ -220,6 +287,12 @@ function getMempoolStats() {
summary["count"]++; summary["count"]++;
summary["totalFees"] += txMempoolInfo.modifiedfee; summary["totalFees"] += txMempoolInfo.modifiedfee;
summary["totalBytes"] += txMempoolInfo.size; summary["totalBytes"] += txMempoolInfo.size;
var ageBucketIndex = Math.min(ageBucketCount - 1, parseInt(age / (maxAge / ageBucketCount)));
var sizeBucketIndex = Math.min(sizeBucketCount - 1, parseInt(size / (maxSize / sizeBucketCount)));
ageBucketTxCounts[ageBucketIndex]++;
sizeBucketTxCounts[sizeBucketIndex]++;
} }
summary["averageFee"] = summary["totalFees"] / summary["count"]; summary["averageFee"] = summary["totalFees"] / summary["count"];
@ -234,6 +307,11 @@ function getMempoolStats() {
summary["satoshiPerByteBucketTotalFees"].push(summary["satoshiPerByteBuckets"][i]["totalFees"]); summary["satoshiPerByteBucketTotalFees"].push(summary["satoshiPerByteBuckets"][i]["totalFees"]);
} }
/*console.log(JSON.stringify(ageBuckets));
console.log(JSON.stringify(ageBucketLabels));
console.log(JSON.stringify(sizeBuckets));
console.log(JSON.stringify(sizeBucketLabels));*/
resolve(summary); resolve(summary);
}); });
}); });

81
views/mempool-summary.pug

@ -96,7 +96,7 @@ block content
} }
}); });
table(class="table table-striped table-responsive-sm") table(class="table table-striped table-responsive-sm mb-4")
thead thead
tr tr
th Fee Rate th Fee Rate
@ -125,4 +125,83 @@ block content
else else
td(class="text-right monospace") - td(class="text-right monospace") -
td(class="text-right monospace") - td(class="text-right monospace") -
h4 Transactions by size
hr
canvas(id="txSizesBarChart", height="100", class="mb-4")
script var sizeBucketLabels = [];
script var bgColors = [];
each sizeBucketLabel, index in mempoolstats["sizeBucketLabels"]
- var percentTx = Math.round(100 * mempoolstats["sizeBucketTxCounts"][index] / getmempoolinfo.size).toLocaleString();
script sizeBucketLabels.push(["#{sizeBucketLabel} bytes","#{mempoolstats["sizeBucketTxCounts"][index]} tx (#{percentTx}%)"]);
script bgColors.push("hsl(#{(333 * index / mempoolstats["sizeBucketLabels"].length)}, 100%, 50%)");
script var sizeBucketTxCounts = [#{mempoolstats["sizeBucketTxCounts"]}];
script.
var ctx = document.getElementById("txSizesBarChart").getContext('2d');
var txSizesBarChart = new Chart(ctx, {
type: 'bar',
data: {
labels: sizeBucketLabels,
datasets: [{
data: sizeBucketTxCounts,
backgroundColor: bgColors
}]
},
options: {
legend: {
display: false
},
scales: {
yAxes: [{
ticks: {
beginAtZero:true
}
}]
}
}
});
h4 Transactions by age
hr
canvas(id="txAgesBarChart", height="100", class="mb-4")
script var ageBucketLabels = [];
script var bgColors = [];
each ageBucketLabel, index in mempoolstats["ageBucketLabels"]
- var percentTx = Math.round(100 * mempoolstats["ageBucketTxCounts"][index] / getmempoolinfo.size).toLocaleString();
script ageBucketLabels.push(["#{ageBucketLabel} sec","#{mempoolstats["ageBucketTxCounts"][index]} tx (#{percentTx}%)"]);
script bgColors.push("hsl(#{(333 * index / mempoolstats["ageBucketLabels"].length)}, 100%, 50%)");
script var ageBucketTxCounts = [#{mempoolstats["ageBucketTxCounts"]}];
script.
var ctx = document.getElementById("txAgesBarChart").getContext('2d');
var txAgesBarChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ageBucketLabels,
datasets: [{
data: ageBucketTxCounts,
backgroundColor: bgColors
}]
},
options: {
legend: {
display: false
},
scales: {
yAxes: [{
ticks: {
beginAtZero:true
}
}]
}
}
});
Loading…
Cancel
Save