Browse Source

blockchain download and import performance optimizations

cl-refactor
arkpar 10 years ago
parent
commit
a1c84c7172
  1. 4
      alethzero/DownloadView.cpp
  2. 13
      libdevcore/Guards.h
  3. 4
      libdevcore/Log.cpp
  4. 11
      libethcore/EthashAux.cpp
  5. 10
      libethereum/BlockChain.cpp
  6. 1
      libethereum/BlockChain.h
  7. 2
      libethereum/DownloadMan.cpp
  8. 3
      libethereum/DownloadMan.h
  9. 2
      libethereum/EthereumHost.cpp
  10. 19
      libethereum/EthereumPeer.cpp

4
alethzero/DownloadView.cpp

@ -39,13 +39,13 @@ void DownloadView::paintEvent(QPaintEvent*)
QPainter p(this);
p.fillRect(rect(), Qt::white);
if (!m_man || m_man->chain().empty() || !m_man->subCount())
if (!m_man || m_man->chainEmpty() || !m_man->subCount())
return;
double ratio = (double)rect().width() / rect().height();
if (ratio < 1)
ratio = 1 / ratio;
double n = min(16.0, min(rect().width(), rect().height()) / ceil(sqrt(m_man->chain().size() / ratio)));
double n = min(16.0, min(rect().width(), rect().height()) / ceil(sqrt(m_man->chainSize() / ratio)));
// QSizeF area(rect().width() / floor(rect().width() / n), rect().height() / floor(rect().height() / n));
QSizeF area(n, n);

13
libdevcore/Guards.h

@ -22,6 +22,7 @@
#pragma once
#include <mutex>
#include <atomic>
#include <boost/thread.hpp>
namespace dev
@ -61,6 +62,18 @@ struct GenericUnguardSharedBool
MutexType& m;
};
/** @brief Simple lock that waits for release without making context switch */
class SpinLock
{
public:
SpinLock() { lck.clear(); }
void lock() { while (lck.test_and_set(std::memory_order_acquire)) {} }
void unlock() { lck.clear(std::memory_order_release); }
private:
std::atomic_flag lck;
};
using SpinGuard = std::lock_guard<SpinLock>;
/** @brief Simple block guard.
* The expression/block following is guarded though the given mutex.
* Usage:

4
libdevcore/Log.cpp

@ -158,8 +158,8 @@ void dev::setThreadName(string const& _n)
void dev::simpleDebugOut(std::string const& _s, char const*)
{
static Mutex s_lock;
Guard l(s_lock);
static SpinLock s_lock;
SpinGuard l(s_lock);
cerr << _s << endl << flush;

11
libethcore/EthashAux.cpp

@ -87,13 +87,10 @@ ethash_params EthashAux::params(h256 const& _seedHash)
{
Guard l(get()->x_epochs);
unsigned epoch = 0;
try
auto epochIter = get()->m_epochs.find(_seedHash);
if (epochIter == get()->m_epochs.end())
{
epoch = get()->m_epochs.at(_seedHash);
}
catch (...)
{
// cdebug << "Searching for seedHash " << _seedHash;
// cdebug << "Searching for seedHash " << _seedHash;
for (h256 h; h != _seedHash && epoch < 2048; ++epoch, h = sha3(h), get()->m_epochs[h] = epoch) {}
if (epoch == 2048)
{
@ -102,6 +99,8 @@ ethash_params EthashAux::params(h256 const& _seedHash)
throw std::invalid_argument(error.str());
}
}
else
epoch = epochIter->second;
return params(epoch * ETHASH_EPOCH_LENGTH);
}

10
libethereum/BlockChain.cpp

@ -293,9 +293,14 @@ LastHashes BlockChain::lastHashes(unsigned _n) const
Guard l(x_lastLastHashes);
if (m_lastLastHashesNumber != _n || m_lastLastHashes.empty())
{
m_lastLastHashes.resize(256);
LastHashes lastHashes(256);
//m_lastLastHashes.resize(256);
for (unsigned i = 0; i < 256; ++i)
m_lastLastHashes[i] = _n >= i ? numberHash(_n - i) : h256();
{
size_t prevIndex = m_lastLastHashesNumber - _n + i;
lastHashes[i] = (prevIndex >= 0 && prevIndex < m_lastLastHashes.size()) ? m_lastLastHashes[prevIndex] : (_n >= i ? numberHash(_n - i) : h256());
}
m_lastLastHashes = std::move(lastHashes);
m_lastLastHashesNumber = _n;
}
return m_lastLastHashes;
@ -609,7 +614,6 @@ ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, Import
}
clog(BlockChainNote) << " Imported and best" << td << " (#" << bi.number << "). Has" << (details(bi.parentHash).children.size() - 1) << "siblings. Route:" << route;
noteCanonChanged();
StructuredLogger::chainNewHead(
bi.headerHash(WithoutNonce).abridged(),

1
libethereum/BlockChain.h

@ -300,7 +300,6 @@ private:
void noteUsed(h256 const& _h, unsigned _extra = (unsigned)-1) const;
std::chrono::system_clock::time_point m_lastCollection;
void noteCanonChanged() const { Guard l(x_lastLastHashes); m_lastLastHashes.clear(); }
mutable Mutex x_lastLastHashes;
mutable LastHashes m_lastLastHashes;
mutable unsigned m_lastLastHashesNumber = (unsigned)-1;

2
libethereum/DownloadMan.cpp

@ -50,7 +50,7 @@ h256Set DownloadSub::nextFetch(unsigned _n)
m_indices.clear();
m_remaining.clear();
if (!m_man || m_man->chain().empty())
if (!m_man || m_man->chainEmpty())
return h256Set();
m_asked = (~(m_man->taken() + m_attempted)).lowest(_n);

3
libethereum/DownloadMan.h

@ -143,7 +143,8 @@ public:
return ret;
}
h256s chain() const { ReadGuard l(m_lock); return m_chain; }
size_t chainSize() const { ReadGuard l(m_lock); return m_chain.size(); }
size_t chainEmpty() const { ReadGuard l(m_lock); return m_chain.empty(); }
void foreachSub(std::function<void(DownloadSub const&)> const& _f) const { ReadGuard l(x_subs); for(auto i: m_subs) _f(*i); }
unsigned subCount() const { ReadGuard l(x_subs); return m_subs.size(); }
RangeMask<unsigned> blocksGot() const { ReadGuard l(m_lock); return m_blocksGot; }

2
libethereum/EthereumHost.cpp

@ -122,7 +122,7 @@ void EthereumHost::noteDoneBlocks(EthereumPeer* _who, bool _clemency)
// Done our chain-get.
clog(NetNote) << "Chain download complete.";
// 1/100th for each useful block hash.
_who->addRating(m_man.chain().size() / 100);
_who->addRating(m_man.chainSize() / 100);
m_man.reset();
}
else if (_who->isSyncing())

19
libethereum/EthereumPeer.cpp

@ -329,9 +329,10 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
case GetTransactionsPacket: break; // DEPRECATED.
case TransactionsPacket:
{
clog(NetAllDetail) << "Transactions (" << dec << _r.itemCount() << "entries)";
unsigned itemCount = _r.itemCount();
clog(NetAllDetail) << "Transactions (" << dec << itemCount << "entries)";
Guard l(x_knownTransactions);
for (unsigned i = 0; i < _r.itemCount(); ++i)
for (unsigned i = 0; i < itemCount; ++i)
{
auto h = sha3(_r[i].data());
m_knownTransactions.insert(h);
@ -373,21 +374,22 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
}
case BlockHashesPacket:
{
clog(NetMessageSummary) << "BlockHashes (" << dec << _r.itemCount() << "entries)" << (_r.itemCount() ? "" : ": NoMoreHashes");
unsigned itemCount = _r.itemCount();
clog(NetMessageSummary) << "BlockHashes (" << dec << itemCount << "entries)" << (itemCount ? "" : ": NoMoreHashes");
if (m_asking != Asking::Hashes)
{
cwarn << "Peer giving us hashes when we didn't ask for them.";
break;
}
if (_r.itemCount() == 0)
if (itemCount == 0)
{
transition(Asking::Blocks);
return true;
}
unsigned knowns = 0;
unsigned unknowns = 0;
for (unsigned i = 0; i < _r.itemCount(); ++i)
for (unsigned i = 0; i < itemCount; ++i)
{
addRating(1);
auto h = _r[i].toHash<h256>();
@ -454,12 +456,13 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
}
case BlocksPacket:
{
clog(NetMessageSummary) << "Blocks (" << dec << _r.itemCount() << "entries)" << (_r.itemCount() ? "" : ": NoMoreBlocks");
unsigned itemCount = _r.itemCount();
clog(NetMessageSummary) << "Blocks (" << dec << itemCount << "entries)" << (itemCount ? "" : ": NoMoreBlocks");
if (m_asking != Asking::Blocks)
clog(NetWarn) << "Unexpected Blocks received!";
if (_r.itemCount() == 0)
if (itemCount == 0)
{
// Got to this peer's latest block - just give up.
transition(Asking::Nothing);
@ -472,7 +475,7 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
unsigned got = 0;
unsigned repeated = 0;
for (unsigned i = 0; i < _r.itemCount(); ++i)
for (unsigned i = 0; i < itemCount; ++i)
{
auto h = BlockInfo::headerHash(_r[i].data());
if (m_sub.noteBlock(h))

Loading…
Cancel
Save