Add histogram to poolstats
This commit is contained in:
parent
d09620b0e2
commit
3fc22e7b78
3 changed files with 105 additions and 3 deletions
|
@ -556,8 +556,9 @@ namespace cryptonote
|
||||||
CRITICAL_REGION_LOCAL(m_transactions_lock);
|
CRITICAL_REGION_LOCAL(m_transactions_lock);
|
||||||
CRITICAL_REGION_LOCAL1(m_blockchain);
|
CRITICAL_REGION_LOCAL1(m_blockchain);
|
||||||
const uint64_t now = time(NULL);
|
const uint64_t now = time(NULL);
|
||||||
|
std::map<uint64_t, txpool_histo> agebytes;
|
||||||
stats.txs_total = m_blockchain.get_txpool_tx_count();
|
stats.txs_total = m_blockchain.get_txpool_tx_count();
|
||||||
m_blockchain.for_all_txpool_txes([&stats, now](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){
|
m_blockchain.for_all_txpool_txes([&stats, now, &agebytes](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){
|
||||||
stats.bytes_total += meta.blob_size;
|
stats.bytes_total += meta.blob_size;
|
||||||
if (!stats.bytes_min || meta.blob_size < stats.bytes_min)
|
if (!stats.bytes_min || meta.blob_size < stats.bytes_min)
|
||||||
stats.bytes_min = meta.blob_size;
|
stats.bytes_min = meta.blob_size;
|
||||||
|
@ -572,8 +573,53 @@ namespace cryptonote
|
||||||
stats.num_10m++;
|
stats.num_10m++;
|
||||||
if (meta.last_failed_height)
|
if (meta.last_failed_height)
|
||||||
stats.num_failing++;
|
stats.num_failing++;
|
||||||
|
uint64_t age = now - meta.receive_time;
|
||||||
|
agebytes[age].txs++;
|
||||||
|
agebytes[age].bytes += meta.blob_size;
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
if (stats.txs_total > 1)
|
||||||
|
{
|
||||||
|
/* looking for 98th percentile */
|
||||||
|
size_t end = stats.txs_total * 0.02;
|
||||||
|
uint64_t delta, factor;
|
||||||
|
std::map<uint64_t, txpool_histo>::iterator it, i2;
|
||||||
|
if (end)
|
||||||
|
{
|
||||||
|
/* If enough txs, spread the first 98% of results across
|
||||||
|
* the first 9 bins, drop final 2% in last bin.
|
||||||
|
*/
|
||||||
|
it=agebytes.end();
|
||||||
|
for (size_t n=0; n <= end; n++, it--);
|
||||||
|
stats.histo_98pc = it->first;
|
||||||
|
factor = 9;
|
||||||
|
delta = it->first;
|
||||||
|
stats.histo.resize(10);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
/* If not enough txs, don't reserve the last slot;
|
||||||
|
* spread evenly across all 10 bins.
|
||||||
|
*/
|
||||||
|
stats.histo_98pc = 0;
|
||||||
|
it = agebytes.end();
|
||||||
|
factor = stats.txs_total > 9 ? 10 : stats.txs_total;
|
||||||
|
delta = now - stats.oldest;
|
||||||
|
stats.histo.resize(factor);
|
||||||
|
}
|
||||||
|
if (!delta)
|
||||||
|
delta = 1;
|
||||||
|
for (i2 = agebytes.begin(); i2 != it; i2++)
|
||||||
|
{
|
||||||
|
size_t i = (i2->first * factor - 1) / delta;
|
||||||
|
stats.histo[i].txs += i2->second.txs;
|
||||||
|
stats.histo[i].bytes += i2->second.bytes;
|
||||||
|
}
|
||||||
|
for (; i2 != agebytes.end(); i2++)
|
||||||
|
{
|
||||||
|
stats.histo[factor].txs += i2->second.txs;
|
||||||
|
stats.histo[factor].bytes += i2->second.bytes;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
//TODO: investigate whether boolean return is appropriate
|
//TODO: investigate whether boolean return is appropriate
|
||||||
|
|
|
@ -92,6 +92,19 @@ namespace {
|
||||||
return s + " " + (t > now ? "in the future" : "ago");
|
return s + " " + (t > now ? "in the future" : "ago");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string get_time_hms(time_t t)
|
||||||
|
{
|
||||||
|
unsigned int hours, minutes, seconds;
|
||||||
|
char buffer[24];
|
||||||
|
hours = t / 3600;
|
||||||
|
t %= 3600;
|
||||||
|
minutes = t / 60;
|
||||||
|
t %= 60;
|
||||||
|
seconds = t;
|
||||||
|
snprintf(buffer, sizeof(buffer), "%02u:%02u:%02u", hours, minutes, seconds);
|
||||||
|
return std::string(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
std::string make_error(const std::string &base, const std::string &status)
|
std::string make_error(const std::string &base, const std::string &status)
|
||||||
{
|
{
|
||||||
if (status == CORE_RPC_STATUS_OK)
|
if (status == CORE_RPC_STATUS_OK)
|
||||||
|
@ -939,7 +952,35 @@ bool t_rpc_command_executor::print_transaction_pool_stats() {
|
||||||
|
|
||||||
tools::msg_writer() << n_transactions << " tx(es), " << res.pool_stats.bytes_total << " bytes total (min " << res.pool_stats.bytes_min << ", max " << res.pool_stats.bytes_max << ", avg " << avg_bytes << ")" << std::endl
|
tools::msg_writer() << n_transactions << " tx(es), " << res.pool_stats.bytes_total << " bytes total (min " << res.pool_stats.bytes_min << ", max " << res.pool_stats.bytes_max << ", avg " << avg_bytes << ")" << std::endl
|
||||||
<< "fees " << cryptonote::print_money(res.pool_stats.fee_total) << " (avg " << cryptonote::print_money(n_transactions ? res.pool_stats.fee_total / n_transactions : 0) << " per tx" << ", " << cryptonote::print_money(res.pool_stats.bytes_total ? res.pool_stats.fee_total / res.pool_stats.bytes_total : 0) << " per byte )" << std::endl
|
<< "fees " << cryptonote::print_money(res.pool_stats.fee_total) << " (avg " << cryptonote::print_money(n_transactions ? res.pool_stats.fee_total / n_transactions : 0) << " per tx" << ", " << cryptonote::print_money(res.pool_stats.bytes_total ? res.pool_stats.fee_total / res.pool_stats.bytes_total : 0) << " per byte )" << std::endl
|
||||||
<< res.pool_stats.num_not_relayed << " not relayed, " << res.pool_stats.num_failing << " failing, " << res.pool_stats.num_10m << " older than 10 minutes (oldest " << (res.pool_stats.oldest == 0 ? "-" : get_human_time_ago(res.pool_stats.oldest, now)) << ")" << std::endl;
|
<< res.pool_stats.num_not_relayed << " not relayed, " << res.pool_stats.num_failing << " failing, " << res.pool_stats.num_10m << " older than 10 minutes (oldest " << (res.pool_stats.oldest == 0 ? "-" : get_human_time_ago(res.pool_stats.oldest, now)) << ")";
|
||||||
|
|
||||||
|
if (n_transactions > 1 && res.pool_stats.histo.size())
|
||||||
|
{
|
||||||
|
std::vector<uint64_t> times;
|
||||||
|
uint64_t numer;
|
||||||
|
size_t i, n = res.pool_stats.histo.size(), denom;
|
||||||
|
times.resize(n);
|
||||||
|
if (res.pool_stats.histo_98pc)
|
||||||
|
{
|
||||||
|
numer = res.pool_stats.histo_98pc;
|
||||||
|
denom = n-1;
|
||||||
|
for (i=0; i<denom; i++)
|
||||||
|
times[i] = i * numer / denom;
|
||||||
|
times[i] = res.pool_stats.oldest;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
numer = now - res.pool_stats.oldest;
|
||||||
|
denom = n;
|
||||||
|
for (i=0; i<denom; i++)
|
||||||
|
times[i] = i * numer / denom;
|
||||||
|
}
|
||||||
|
tools::msg_writer() << " Age Txes Bytes";
|
||||||
|
for (i=0; i<n; i++)
|
||||||
|
{
|
||||||
|
tools::msg_writer() << get_time_hms(times[i]) << setw(8) << res.pool_stats.histo[i].txs << setw(12) << res.pool_stats.histo[i].bytes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tools::msg_writer();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ namespace cryptonote
|
||||||
// advance which version they will stop working with
|
// advance which version they will stop working with
|
||||||
// Don't go over 32767 for any of these
|
// Don't go over 32767 for any of these
|
||||||
#define CORE_RPC_VERSION_MAJOR 1
|
#define CORE_RPC_VERSION_MAJOR 1
|
||||||
#define CORE_RPC_VERSION_MINOR 11
|
#define CORE_RPC_VERSION_MINOR 12
|
||||||
#define MAKE_CORE_RPC_VERSION(major,minor) (((major)<<16)|(minor))
|
#define MAKE_CORE_RPC_VERSION(major,minor) (((major)<<16)|(minor))
|
||||||
#define CORE_RPC_VERSION MAKE_CORE_RPC_VERSION(CORE_RPC_VERSION_MAJOR, CORE_RPC_VERSION_MINOR)
|
#define CORE_RPC_VERSION MAKE_CORE_RPC_VERSION(CORE_RPC_VERSION_MAJOR, CORE_RPC_VERSION_MINOR)
|
||||||
|
|
||||||
|
@ -1047,6 +1047,17 @@ namespace cryptonote
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct txpool_histo
|
||||||
|
{
|
||||||
|
uint32_t txs;
|
||||||
|
uint64_t bytes;
|
||||||
|
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
KV_SERIALIZE(txs)
|
||||||
|
KV_SERIALIZE(bytes)
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
|
||||||
struct txpool_stats
|
struct txpool_stats
|
||||||
{
|
{
|
||||||
uint64_t bytes_total;
|
uint64_t bytes_total;
|
||||||
|
@ -1058,6 +1069,8 @@ namespace cryptonote
|
||||||
uint32_t num_failing;
|
uint32_t num_failing;
|
||||||
uint32_t num_10m;
|
uint32_t num_10m;
|
||||||
uint32_t num_not_relayed;
|
uint32_t num_not_relayed;
|
||||||
|
uint64_t histo_98pc;
|
||||||
|
std::vector<txpool_histo> histo;
|
||||||
|
|
||||||
BEGIN_KV_SERIALIZE_MAP()
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
KV_SERIALIZE(bytes_total)
|
KV_SERIALIZE(bytes_total)
|
||||||
|
@ -1069,6 +1082,8 @@ namespace cryptonote
|
||||||
KV_SERIALIZE(num_failing)
|
KV_SERIALIZE(num_failing)
|
||||||
KV_SERIALIZE(num_10m)
|
KV_SERIALIZE(num_10m)
|
||||||
KV_SERIALIZE(num_not_relayed)
|
KV_SERIALIZE(num_not_relayed)
|
||||||
|
KV_SERIALIZE(histo_98pc)
|
||||||
|
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(histo)
|
||||||
END_KV_SERIALIZE_MAP()
|
END_KV_SERIALIZE_MAP()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue