Auto merge of #4623 - str4d:metrics-locking, r=str4d
metrics: Collect general stats before clearing screen This prevents the metrics screen from flashing if locks are being held by long-running processes, specifically cs_main during block validation. We split up locking on cs_main and cs_vNodes to make obtaining the locks easier, at the expense of potentially having slightly out-of-sync statistics (which doesn't really matter, as all we are fetching from the latter lock is the number of connected peers).
This commit is contained in:
commit
24f3bcf275
|
@ -14,6 +14,7 @@
|
|||
#include "utilmoneystr.h"
|
||||
#include "utilstrencodings.h"
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/range/irange.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/thread/synchronized_value.hpp>
|
||||
|
@ -284,43 +285,71 @@ boost::optional<int64_t> SecondsLeftToNextEpoch(const Consensus::Params& params,
|
|||
}
|
||||
}
|
||||
|
||||
int printStats(bool isScreen, bool mining)
|
||||
{
|
||||
// Number of lines that are always displayed
|
||||
int lines = 5;
|
||||
|
||||
struct MetricsStats {
|
||||
int height;
|
||||
int64_t currentHeadersHeight;
|
||||
int64_t currentHeadersTime;
|
||||
size_t connections;
|
||||
int64_t netsolps;
|
||||
const Consensus::Params& params = Params().GetConsensus();
|
||||
};
|
||||
|
||||
MetricsStats loadStats()
|
||||
{
|
||||
int height;
|
||||
int64_t currentHeadersHeight;
|
||||
int64_t currentHeadersTime;
|
||||
size_t connections;
|
||||
int64_t netsolps;
|
||||
|
||||
{
|
||||
LOCK2(cs_main, cs_vNodes);
|
||||
LOCK(cs_main);
|
||||
height = chainActive.Height();
|
||||
currentHeadersHeight = pindexBestHeader ? pindexBestHeader->nHeight: -1;
|
||||
currentHeadersTime = pindexBestHeader ? pindexBestHeader->nTime : 0;
|
||||
connections = vNodes.size();
|
||||
netsolps = GetNetworkHashPS(120, -1);
|
||||
}
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
connections = vNodes.size();
|
||||
}
|
||||
|
||||
return MetricsStats {
|
||||
height,
|
||||
currentHeadersHeight,
|
||||
currentHeadersTime,
|
||||
connections,
|
||||
netsolps
|
||||
};
|
||||
}
|
||||
|
||||
int printStats(MetricsStats stats, bool isScreen, bool mining)
|
||||
{
|
||||
// Number of lines that are always displayed
|
||||
int lines = 5;
|
||||
|
||||
const Consensus::Params& params = Params().GetConsensus();
|
||||
auto localsolps = GetLocalSolPS();
|
||||
|
||||
if (IsInitialBlockDownload(Params())) {
|
||||
if (fReindex) {
|
||||
int downloadPercent = nSizeReindexed * 100 / nFullSizeToReindex;
|
||||
std::cout << " " << _("Reindexing blocks") << " | " << DisplaySize(nSizeReindexed) << " / " << DisplaySize(nFullSizeToReindex) << " (" << downloadPercent << "%, " << height << " " << _("blocks") << ")" << std::endl;
|
||||
std::cout << " " << _("Reindexing blocks") << " | "
|
||||
<< DisplaySize(nSizeReindexed) << " / " << DisplaySize(nFullSizeToReindex)
|
||||
<< " (" << downloadPercent << "%, " << stats.height << " " << _("blocks") << ")" << std::endl;
|
||||
} else {
|
||||
int nHeaders = currentHeadersHeight;
|
||||
int nHeaders = stats.currentHeadersHeight;
|
||||
if (nHeaders < 0)
|
||||
nHeaders = 0;
|
||||
int netheight = currentHeadersHeight == -1 || currentHeadersTime == 0 ?
|
||||
0 : EstimateNetHeight(params, currentHeadersHeight, currentHeadersTime);
|
||||
int netheight = stats.currentHeadersHeight == -1 || stats.currentHeadersTime == 0 ?
|
||||
0 : EstimateNetHeight(params, stats.currentHeadersHeight, stats.currentHeadersTime);
|
||||
if (netheight < nHeaders)
|
||||
netheight = nHeaders;
|
||||
if (netheight <= 0)
|
||||
netheight = 1;
|
||||
int downloadPercent = height * 100 / netheight;
|
||||
std::cout << " " << _("Downloading blocks") << " | " << height << " (" << nHeaders << " " << _("headers") << ") / ~" << netheight << " (" << downloadPercent << "%)" << std::endl;
|
||||
int downloadPercent = stats.height * 100 / netheight;
|
||||
std::cout << " " << _("Downloading blocks") << " | "
|
||||
<< stats.height << " (" << nHeaders << " " << _("headers") << ") / ~" << netheight
|
||||
<< " (" << downloadPercent << "%)" << std::endl;
|
||||
|
||||
if (isScreen) {
|
||||
// Draw 50-character progress bar, which will fit into a 79-character line.
|
||||
|
@ -344,14 +373,14 @@ int printStats(bool isScreen, bool mining)
|
|||
}
|
||||
}
|
||||
} else {
|
||||
std::cout << " " << _("Block height") << " | " << height << std::endl;
|
||||
std::cout << " " << _("Block height") << " | " << stats.height << std::endl;
|
||||
}
|
||||
|
||||
auto secondsLeft = SecondsLeftToNextEpoch(params, height);
|
||||
auto secondsLeft = SecondsLeftToNextEpoch(params, stats.height);
|
||||
std::string strUpgradeTime;
|
||||
if (secondsLeft) {
|
||||
auto nextHeight = NextActivationHeight(height, params).value();
|
||||
auto nextBranch = NextEpoch(height, params).value();
|
||||
auto nextHeight = NextActivationHeight(stats.height, params).value();
|
||||
auto nextBranch = NextEpoch(stats.height, params).value();
|
||||
strUpgradeTime = strprintf(_("%s at block height %d, in around %s"),
|
||||
NetworkUpgradeInfo[nextBranch].strName, nextHeight, DisplayDuration(secondsLeft.value(), DurationFormat::REDUCED));
|
||||
}
|
||||
|
@ -359,8 +388,8 @@ int printStats(bool isScreen, bool mining)
|
|||
strUpgradeTime = "Unknown";
|
||||
}
|
||||
std::cout << " " << _("Next upgrade") << " | " << strUpgradeTime << std::endl;
|
||||
std::cout << " " << _("Connections") << " | " << connections << std::endl;
|
||||
std::cout << " " << _("Network solution rate") << " | " << DisplayHashRate(netsolps) << std::endl;
|
||||
std::cout << " " << _("Connections") << " | " << stats.connections << std::endl;
|
||||
std::cout << " " << _("Network solution rate") << " | " << DisplayHashRate(stats.netsolps) << std::endl;
|
||||
if (mining && miningTimer.running()) {
|
||||
std::cout << " " << _("Local solution rate") << " | " << DisplayHashRate(localsolps) << std::endl;
|
||||
lines++;
|
||||
|
@ -611,6 +640,12 @@ void ThreadShowMetricsScreen()
|
|||
#endif
|
||||
}
|
||||
|
||||
// Lock and fetch stats before erasing the screen, in case we block.
|
||||
boost::optional<MetricsStats> metricsStats;
|
||||
if (loaded) {
|
||||
metricsStats = loadStats();
|
||||
}
|
||||
|
||||
if (isScreen) {
|
||||
// Erase below current position
|
||||
std::cout << "\e[J";
|
||||
|
@ -624,7 +659,7 @@ void ThreadShowMetricsScreen()
|
|||
#endif
|
||||
|
||||
if (loaded) {
|
||||
lines += printStats(isScreen, mining);
|
||||
lines += printStats(metricsStats.value(), isScreen, mining);
|
||||
lines += printMiningStatus(mining);
|
||||
}
|
||||
lines += printMetrics(cols, mining);
|
||||
|
|
Loading…
Reference in New Issue