Skip to content

Commit 2f7926e

Browse files
committed
[Mining] Reduce lock contention with SHA256D
Increases the number of hashes a SHA256D miner thread attempts per created block template, and adds a separate counter to allow an early continuation when the chain tip changes. The SHA256D algorithm is fast enough that the main miner loop runs multiple times per second with the previous loop count. In each loop, a thread generates a new block template, which requires grabbing cs_main a couple times. I found this to be a significant source of contention, often causing both SHA mining and wallet syncing to stop. In contrast, a RandomX miner thread runs its main loop on the order of minutes, with a lower loop count, and checks on every hash attempt whether the tip has changed, resulting in approximately one block template created per block. I chose nMidLoopCount to approximately match the RandomX timing, while nInnerLoopCount is still fast enough to be used as an intermittent sub-second check of the chain height.
1 parent 4f4528c commit 2f7926e

File tree

1 file changed

+28
-8
lines changed

1 file changed

+28
-8
lines changed

src/miner.cpp

+28-8
Original file line numberDiff line numberDiff line change
@@ -869,6 +869,7 @@ void BitcoinMiner(std::shared_ptr<CReserveScript> coinbaseScript, bool fProofOfS
869869
enablewallet = !gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET);
870870
#endif
871871

872+
bool fBlockFoundAlready = false;
872873
while (!ShutdownRequested() && (GenerateActive() || (fProofOfStake && enablewallet)))
873874
{
874875
boost::this_thread::interruption_point();
@@ -985,6 +986,12 @@ void BitcoinMiner(std::shared_ptr<CReserveScript> coinbaseScript, bool fProofOfS
985986
IncrementExtraNonce(pblock, nHeight, nExtraNonce);
986987

987988
int nTries = 0;
989+
// As SHA runs much faster than the other algorithms, run more of them in this section
990+
// to avoid lock contention from creating block templates. Use a separate counter
991+
// nMidLoopCount to keep track of this, so that we can check every nInnerLoopCount hashes
992+
// if the block is done.
993+
int nMidTries = 0;
994+
static const int nMidLoopCount = 0x1000;
988995
if (pblock->IsProgPow() && pblock->nTime >= Params().PowUpdateTimestamp()) {
989996
uint256 mix_hash;
990997
while (nTries < nInnerLoopCount &&
@@ -997,12 +1004,24 @@ void BitcoinMiner(std::shared_ptr<CReserveScript> coinbaseScript, bool fProofOfS
9971004
pblock->mixHash = mix_hash;
9981005
} else if (pblock->IsSha256D() && pblock->nTime >= Params().PowUpdateTimestamp()) {
9991006
uint256 midStateHash = pblock->GetSha256dMidstate();
1000-
while (nTries < nInnerLoopCount &&
1001-
!CheckProofOfWork(pblock->GetSha256D(midStateHash), pblock->nBits,
1002-
Params().GetConsensus(), CBlockHeader::SHA256D_BLOCK)) {
1003-
boost::this_thread::interruption_point();
1004-
++nTries;
1005-
++pblock->nNonce64;
1007+
bool success = false;
1008+
while (nMidTries < nMidLoopCount) {
1009+
while (nTries < nInnerLoopCount &&
1010+
!(success = CheckProofOfWork(pblock->GetSha256D(midStateHash), pblock->nBits,
1011+
Params().GetConsensus(), CBlockHeader::SHA256D_BLOCK))) {
1012+
boost::this_thread::interruption_point();
1013+
++nTries;
1014+
++pblock->nNonce64;
1015+
}
1016+
if (success) {
1017+
break;
1018+
}
1019+
++nMidTries;
1020+
nTries = 0;
1021+
if (pblock->nHeight <= chainActive.Height()) {
1022+
fBlockFoundAlready = true;
1023+
break;
1024+
}
10061025
}
10071026
} else if (pblock->nTime < Params().PowUpdateTimestamp()) {
10081027
while (nTries < nInnerLoopCount &&
@@ -1019,14 +1038,15 @@ void BitcoinMiner(std::shared_ptr<CReserveScript> coinbaseScript, bool fProofOfS
10191038
double nHashSpeed = 0;
10201039
{
10211040
LOCK(cs_nonce);
1022-
nHashes += nTries;
1041+
nHashes += nTries + (nMidTries * nInnerLoopCount);
10231042
nTimeDuration = GetTime() - nTimeStart;
10241043
if (!nTimeDuration) nTimeDuration = 1;
10251044
nHashSpeed = arith_uint256(nHashes/1000/nTimeDuration).getdouble();
10261045
}
10271046

10281047
LogPrint(BCLog::MINING, "%s: PoW Hashspeed %d kh/s\n", __func__, nHashSpeed);
1029-
if (nTries == nInnerLoopCount) {
1048+
if (nMidTries == nMidLoopCount || fBlockFoundAlready) {
1049+
fBlockFoundAlready = false;
10301050
continue;
10311051
}
10321052
}

0 commit comments

Comments
 (0)