diff --git a/alethzero/DownloadView.cpp b/alethzero/DownloadView.cpp index 88a595566..009e2dc83 100644 --- a/alethzero/DownloadView.cpp +++ b/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); diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake index 416bb3095..9e9ae687e 100644 --- a/cmake/EthCompilerSettings.cmake +++ b/cmake/EthCompilerSettings.cmake @@ -9,14 +9,6 @@ if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG -DETH_RELEASE") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g -DETH_RELEASE") - if (PROFILING) - set(CMAKE_CXX_FLAGS "-g ${CMAKE_CXX_FLAGS}") - add_definitions(-DETH_PROFILING_GPERF) - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -lprofiler") -# set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} -lprofiler") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lprofiler") - endif () - execute_process( COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION) if (NOT (GCC_VERSION VERSION_GREATER 4.7 OR GCC_VERSION VERSION_EQUAL 4.7)) @@ -61,6 +53,14 @@ else () message(WARNING "Your compiler is not tested, if you run into any issues, we'd welcome any patches.") endif () +if (PROFILING AND (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang"))) + set(CMAKE_CXX_FLAGS "-g ${CMAKE_CXX_FLAGS}") + add_definitions(-DETH_PROFILING_GPERF) + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -lprofiler") +# set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} -lprofiler") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lprofiler") +endif () + if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")) option(USE_LD_GOLD "Use GNU gold linker" ON) if (USE_LD_GOLD) diff --git a/libdevcore/FixedHash.h b/libdevcore/FixedHash.h index 456365299..2cf81cb77 100644 --- a/libdevcore/FixedHash.h +++ b/libdevcore/FixedHash.h @@ -64,6 +64,9 @@ public: /// Convert from the corresponding arithmetic type. FixedHash(Arith const& _arith) { toBigEndian(_arith, m_data); } + /// Convert from unsigned + explicit FixedHash(unsigned _u) { toBigEndian(_u, m_data); } + /// Explicitly construct, copying from a byte array. explicit FixedHash(bytes const& _b, ConstructFromHashType _t = FailIfDifferent) { if (_b.size() == N) memcpy(m_data.data(), _b.data(), std::min(_b.size(), N)); else { m_data.fill(0); if (_t != FailIfDifferent) { auto c = std::min(_b.size(), N); for (unsigned i = 0; i < c; ++i) m_data[_t == AlignRight ? N - 1 - i : i] = _b[_t == AlignRight ? _b.size() - 1 - i : i]; } } } @@ -80,7 +83,7 @@ public: operator Arith() const { return fromBigEndian(m_data); } /// @returns true iff this is the empty hash. - explicit operator bool() const { return ((Arith)*this) != 0; } + explicit operator bool() const { return std::any_of(m_data.begin(), m_data.end(), [](byte _b) { return _b != 0; }); } // The obvious comparison operators. bool operator==(FixedHash const& _c) const { return m_data == _c.m_data; } diff --git a/libdevcore/Guards.h b/libdevcore/Guards.h index 4229428ce..d060108ef 100644 --- a/libdevcore/Guards.h +++ b/libdevcore/Guards.h @@ -22,6 +22,7 @@ #pragma once #include +#include #include 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() { m_lock.clear(); } + void lock() { while (m_lock.test_and_set(std::memory_order_acquire)) {} } + void unlock() { m_lock.clear(std::memory_order_release); } +private: + std::atomic_flag m_lock; +}; +using SpinGuard = std::lock_guard; + /** @brief Simple block guard. * The expression/block following is guarded though the given mutex. * Usage: diff --git a/libdevcore/Log.cpp b/libdevcore/Log.cpp index e086278ec..3dd2b3879 100644 --- a/libdevcore/Log.cpp +++ b/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; diff --git a/libethcore/EthashAux.cpp b/libethcore/EthashAux.cpp index 9cb4d9fad..dd7e92a66 100644 --- a/libethcore/EthashAux.cpp +++ b/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); } diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index 69078b400..204203c9d 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -767,7 +767,7 @@ void BlockChain::noteUsed(h256 const& _h, unsigned _extra) const m_inUse.insert(id); } -template static unsigned getHashSize(map const& _map) +template static unsigned getHashSize(unordered_map const& _map) { unsigned ret = 0; for (auto const& i: _map) @@ -855,7 +855,7 @@ void BlockChain::garbageCollect(bool _force) } } m_cacheUsage.pop_back(); - m_cacheUsage.push_front(std::set{}); + m_cacheUsage.push_front(std::unordered_set{}); } void BlockChain::checkConsistency() diff --git a/libethereum/BlockChain.h b/libethereum/BlockChain.h index d04bff298..12e1fc785 100644 --- a/libethereum/BlockChain.h +++ b/libethereum/BlockChain.h @@ -28,6 +28,8 @@ #include #include +#include +#include #include #include #include @@ -40,6 +42,14 @@ #include "BlockQueue.h" namespace ldb = leveldb; +namespace std +{ +template <> struct hash> +{ + size_t operator()(pair const& _x) const { return hash()(_x.first) ^ hash()(_x.second); } +}; +} + namespace dev { @@ -66,7 +76,7 @@ std::map const& genesisState(); ldb::Slice toSlice(h256 const& _h, unsigned _sub = 0); -using BlocksHash = std::map; +using BlocksHash = std::unordered_map; using TransactionHashes = h256s; using UncleHashes = h256s; using ImportRoute = std::pair; @@ -144,7 +154,7 @@ public: UncleHashes uncleHashes() const { return uncleHashes(currentHash()); } /// Get the hash for a given block's number. - h256 numberHash(unsigned _i) const { if (!_i) return genesisHash(); return queryExtras(h256(u256(_i)), m_blockHashes, x_blockHashes, NullBlockHash).value; } + h256 numberHash(unsigned _i) const { if (!_i) return genesisHash(); return queryExtras(h256(_i), m_blockHashes, x_blockHashes, NullBlockHash).value; } /// Get the last N hashes for a given block. (N is determined by the LastHashes type.) LastHashes lastHashes() const { return lastHashes(number()); } @@ -251,7 +261,7 @@ private: void open(std::string const& _path, WithExisting _we = WithExisting::Trust); void close(); - template T queryExtras(h256 const& _h, std::map& _m, boost::shared_mutex& _x, T const& _n, ldb::DB* _extrasDB = nullptr) const + template T queryExtras(h256 const& _h, std::unordered_map& _m, boost::shared_mutex& _x, T const& _n, ldb::DB* _extrasDB = nullptr) const { { ReadGuard l(_x); @@ -295,8 +305,8 @@ private: using CacheID = std::pair; mutable Mutex x_cacheUsage; - mutable std::deque> m_cacheUsage; - mutable std::set m_inUse; + mutable std::deque> m_cacheUsage; + mutable std::unordered_set m_inUse; void noteUsed(h256 const& _h, unsigned _extra = (unsigned)-1) const; std::chrono::system_clock::time_point m_lastCollection; diff --git a/libethereum/BlockDetails.h b/libethereum/BlockDetails.h index 0baacb4da..19e2c7c7a 100644 --- a/libethereum/BlockDetails.h +++ b/libethereum/BlockDetails.h @@ -21,6 +21,7 @@ #pragma once +#include #pragma warning(push) #pragma warning(disable: 4100 4267) #include @@ -114,12 +115,12 @@ struct TransactionAddress static const unsigned size = 67; }; -using BlockDetailsHash = std::map; -using BlockLogBloomsHash = std::map; -using BlockReceiptsHash = std::map; -using TransactionAddressHash = std::map; -using BlockHashHash = std::map; -using BlocksBloomsHash = std::map; +using BlockDetailsHash = std::unordered_map; +using BlockLogBloomsHash = std::unordered_map; +using BlockReceiptsHash = std::unordered_map; +using TransactionAddressHash = std::unordered_map; +using BlockHashHash = std::unordered_map; +using BlocksBloomsHash = std::unordered_map; static const BlockDetails NullBlockDetails; static const BlockLogBlooms NullBlockLogBlooms; diff --git a/libethereum/DownloadMan.cpp b/libethereum/DownloadMan.cpp index be33f5187..1b73dca5b 100644 --- a/libethereum/DownloadMan.cpp +++ b/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); diff --git a/libethereum/DownloadMan.h b/libethereum/DownloadMan.h index d32d0465c..82e0f09e2 100644 --- a/libethereum/DownloadMan.h +++ b/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 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 blocksGot() const { ReadGuard l(m_lock); return m_blocksGot; } diff --git a/libethereum/EthereumHost.cpp b/libethereum/EthereumHost.cpp index c98dd7642..340ae417f 100644 --- a/libethereum/EthereumHost.cpp +++ b/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()) diff --git a/libethereum/EthereumPeer.cpp b/libethereum/EthereumPeer.cpp index f3edaf8ea..249831540 100644 --- a/libethereum/EthereumPeer.cpp +++ b/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(); @@ -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))