diff options
-rw-r--r-- | src/cryptonote_core/tx_pool.cpp | 48 | ||||
-rw-r--r-- | src/daemon/rpc_command_executor.cpp | 43 | ||||
-rw-r--r-- | src/rpc/core_rpc_server_commands_defs.h | 17 |
3 files changed, 105 insertions, 3 deletions
diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index 515918cfa..589162a3e 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -556,8 +556,9 @@ namespace cryptonote CRITICAL_REGION_LOCAL(m_transactions_lock); CRITICAL_REGION_LOCAL1(m_blockchain); const uint64_t now = time(NULL); + std::map<uint64_t, txpool_histo> agebytes; 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; if (!stats.bytes_min || meta.blob_size < stats.bytes_min) stats.bytes_min = meta.blob_size; @@ -572,8 +573,53 @@ namespace cryptonote stats.num_10m++; if (meta.last_failed_height) stats.num_failing++; + uint64_t age = now - meta.receive_time; + agebytes[age].txs++; + agebytes[age].bytes += meta.blob_size; 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 diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp index d5bde7f09..1c9cd714d 100644 --- a/src/daemon/rpc_command_executor.cpp +++ b/src/daemon/rpc_command_executor.cpp @@ -92,6 +92,19 @@ namespace { 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) { 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 << "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; } diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index f5fe46375..7a1f5a963 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -49,7 +49,7 @@ namespace cryptonote // advance which version they will stop working with // Don't go over 32767 for any of these #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 CORE_RPC_VERSION MAKE_CORE_RPC_VERSION(CORE_RPC_VERSION_MAJOR, CORE_RPC_VERSION_MINOR) @@ -1052,6 +1052,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 { uint64_t bytes_total; @@ -1063,6 +1074,8 @@ namespace cryptonote uint32_t num_failing; uint32_t num_10m; uint32_t num_not_relayed; + uint64_t histo_98pc; + std::vector<txpool_histo> histo; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(bytes_total) @@ -1074,6 +1087,8 @@ namespace cryptonote KV_SERIALIZE(num_failing) KV_SERIALIZE(num_10m) KV_SERIALIZE(num_not_relayed) + KV_SERIALIZE(histo_98pc) + KV_SERIALIZE_CONTAINER_POD_AS_BLOB(histo) END_KV_SERIALIZE_MAP() }; |