Browse Source

Merge branch 'arkpar-core_perf' into develop

cl-refactor
Gav Wood 10 years ago
parent
commit
e08d6bb8eb
  1. 4
      alethzero/DownloadView.cpp
  2. 16
      cmake/EthCompilerSettings.cmake
  3. 5
      libdevcore/FixedHash.h
  4. 13
      libdevcore/Guards.h
  5. 4
      libdevcore/Log.cpp
  6. 11
      libethcore/EthashAux.cpp
  7. 4
      libethereum/BlockChain.cpp
  8. 20
      libethereum/BlockChain.h
  9. 13
      libethereum/BlockDetails.h
  10. 2
      libethereum/DownloadMan.cpp
  11. 3
      libethereum/DownloadMan.h
  12. 2
      libethereum/EthereumHost.cpp
  13. 19
      libethereum/EthereumPeer.cpp

4
alethzero/DownloadView.cpp

@ -39,13 +39,13 @@ void DownloadView::paintEvent(QPaintEvent*)
QPainter p(this); QPainter p(this);
p.fillRect(rect(), Qt::white); 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; return;
double ratio = (double)rect().width() / rect().height(); double ratio = (double)rect().width() / rect().height();
if (ratio < 1) if (ratio < 1)
ratio = 1 / ratio; 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(rect().width() / floor(rect().width() / n), rect().height() / floor(rect().height() / n));
QSizeF area(n, n); QSizeF area(n, n);

16
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_RELEASE "-O3 -DNDEBUG -DETH_RELEASE")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g -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( execute_process(
COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION) COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION)
if (NOT (GCC_VERSION VERSION_GREATER 4.7 OR GCC_VERSION VERSION_EQUAL 4.7)) 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.") message(WARNING "Your compiler is not tested, if you run into any issues, we'd welcome any patches.")
endif () 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")) if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang"))
option(USE_LD_GOLD "Use GNU gold linker" ON) option(USE_LD_GOLD "Use GNU gold linker" ON)
if (USE_LD_GOLD) if (USE_LD_GOLD)

5
libdevcore/FixedHash.h

@ -64,6 +64,9 @@ public:
/// Convert from the corresponding arithmetic type. /// Convert from the corresponding arithmetic type.
FixedHash(Arith const& _arith) { toBigEndian(_arith, m_data); } 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. /// 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<unsigned>(_b.size(), N)); else { m_data.fill(0); if (_t != FailIfDifferent) { auto c = std::min<unsigned>(_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]; } } } explicit FixedHash(bytes const& _b, ConstructFromHashType _t = FailIfDifferent) { if (_b.size() == N) memcpy(m_data.data(), _b.data(), std::min<unsigned>(_b.size(), N)); else { m_data.fill(0); if (_t != FailIfDifferent) { auto c = std::min<unsigned>(_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<Arith>(m_data); } operator Arith() const { return fromBigEndian<Arith>(m_data); }
/// @returns true iff this is the empty hash. /// @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. // The obvious comparison operators.
bool operator==(FixedHash const& _c) const { return m_data == _c.m_data; } bool operator==(FixedHash const& _c) const { return m_data == _c.m_data; }

13
libdevcore/Guards.h

@ -22,6 +22,7 @@
#pragma once #pragma once
#include <mutex> #include <mutex>
#include <atomic>
#include <boost/thread.hpp> #include <boost/thread.hpp>
namespace dev namespace dev
@ -61,6 +62,18 @@ struct GenericUnguardSharedBool
MutexType& m; 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<SpinLock>;
/** @brief Simple block guard. /** @brief Simple block guard.
* The expression/block following is guarded though the given mutex. * The expression/block following is guarded though the given mutex.
* Usage: * Usage:

4
libdevcore/Log.cpp

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

11
libethcore/EthashAux.cpp

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

4
libethereum/BlockChain.cpp

@ -767,7 +767,7 @@ void BlockChain::noteUsed(h256 const& _h, unsigned _extra) const
m_inUse.insert(id); m_inUse.insert(id);
} }
template <class T> static unsigned getHashSize(map<h256, T> const& _map) template <class T> static unsigned getHashSize(unordered_map<h256, T> const& _map)
{ {
unsigned ret = 0; unsigned ret = 0;
for (auto const& i: _map) for (auto const& i: _map)
@ -855,7 +855,7 @@ void BlockChain::garbageCollect(bool _force)
} }
} }
m_cacheUsage.pop_back(); m_cacheUsage.pop_back();
m_cacheUsage.push_front(std::set<CacheID>{}); m_cacheUsage.push_front(std::unordered_set<CacheID>{});
} }
void BlockChain::checkConsistency() void BlockChain::checkConsistency()

20
libethereum/BlockChain.h

@ -28,6 +28,8 @@
#include <deque> #include <deque>
#include <chrono> #include <chrono>
#include <unordered_map>
#include <unordered_set>
#include <libdevcore/Log.h> #include <libdevcore/Log.h>
#include <libdevcore/Exceptions.h> #include <libdevcore/Exceptions.h>
#include <libdevcore/Guards.h> #include <libdevcore/Guards.h>
@ -40,6 +42,14 @@
#include "BlockQueue.h" #include "BlockQueue.h"
namespace ldb = leveldb; namespace ldb = leveldb;
namespace std
{
template <> struct hash<pair<dev::h256, unsigned>>
{
size_t operator()(pair<dev::h256, unsigned> const& _x) const { return hash<dev::h256>()(_x.first) ^ hash<unsigned>()(_x.second); }
};
}
namespace dev namespace dev
{ {
@ -66,7 +76,7 @@ std::map<Address, Account> const& genesisState();
ldb::Slice toSlice(h256 const& _h, unsigned _sub = 0); ldb::Slice toSlice(h256 const& _h, unsigned _sub = 0);
using BlocksHash = std::map<h256, bytes>; using BlocksHash = std::unordered_map<h256, bytes>;
using TransactionHashes = h256s; using TransactionHashes = h256s;
using UncleHashes = h256s; using UncleHashes = h256s;
using ImportRoute = std::pair<h256s, h256s>; using ImportRoute = std::pair<h256s, h256s>;
@ -144,7 +154,7 @@ public:
UncleHashes uncleHashes() const { return uncleHashes(currentHash()); } UncleHashes uncleHashes() const { return uncleHashes(currentHash()); }
/// Get the hash for a given block's number. /// Get the hash for a given block's number.
h256 numberHash(unsigned _i) const { if (!_i) return genesisHash(); return queryExtras<BlockHash, ExtraBlockHash>(h256(u256(_i)), m_blockHashes, x_blockHashes, NullBlockHash).value; } h256 numberHash(unsigned _i) const { if (!_i) return genesisHash(); return queryExtras<BlockHash, ExtraBlockHash>(h256(_i), m_blockHashes, x_blockHashes, NullBlockHash).value; }
/// Get the last N hashes for a given block. (N is determined by the LastHashes type.) /// Get the last N hashes for a given block. (N is determined by the LastHashes type.)
LastHashes lastHashes() const { return lastHashes(number()); } LastHashes lastHashes() const { return lastHashes(number()); }
@ -251,7 +261,7 @@ private:
void open(std::string const& _path, WithExisting _we = WithExisting::Trust); void open(std::string const& _path, WithExisting _we = WithExisting::Trust);
void close(); void close();
template<class T, unsigned N> T queryExtras(h256 const& _h, std::map<h256, T>& _m, boost::shared_mutex& _x, T const& _n, ldb::DB* _extrasDB = nullptr) const template<class T, unsigned N> T queryExtras(h256 const& _h, std::unordered_map<h256, T>& _m, boost::shared_mutex& _x, T const& _n, ldb::DB* _extrasDB = nullptr) const
{ {
{ {
ReadGuard l(_x); ReadGuard l(_x);
@ -295,8 +305,8 @@ private:
using CacheID = std::pair<h256, unsigned>; using CacheID = std::pair<h256, unsigned>;
mutable Mutex x_cacheUsage; mutable Mutex x_cacheUsage;
mutable std::deque<std::set<CacheID>> m_cacheUsage; mutable std::deque<std::unordered_set<CacheID>> m_cacheUsage;
mutable std::set<CacheID> m_inUse; mutable std::unordered_set<CacheID> m_inUse;
void noteUsed(h256 const& _h, unsigned _extra = (unsigned)-1) const; void noteUsed(h256 const& _h, unsigned _extra = (unsigned)-1) const;
std::chrono::system_clock::time_point m_lastCollection; std::chrono::system_clock::time_point m_lastCollection;

13
libethereum/BlockDetails.h

@ -21,6 +21,7 @@
#pragma once #pragma once
#include <unordered_map>
#pragma warning(push) #pragma warning(push)
#pragma warning(disable: 4100 4267) #pragma warning(disable: 4100 4267)
#include <leveldb/db.h> #include <leveldb/db.h>
@ -114,12 +115,12 @@ struct TransactionAddress
static const unsigned size = 67; static const unsigned size = 67;
}; };
using BlockDetailsHash = std::map<h256, BlockDetails>; using BlockDetailsHash = std::unordered_map<h256, BlockDetails>;
using BlockLogBloomsHash = std::map<h256, BlockLogBlooms>; using BlockLogBloomsHash = std::unordered_map<h256, BlockLogBlooms>;
using BlockReceiptsHash = std::map<h256, BlockReceipts>; using BlockReceiptsHash = std::unordered_map<h256, BlockReceipts>;
using TransactionAddressHash = std::map<h256, TransactionAddress>; using TransactionAddressHash = std::unordered_map<h256, TransactionAddress>;
using BlockHashHash = std::map<h256, BlockHash>; using BlockHashHash = std::unordered_map<h256, BlockHash>;
using BlocksBloomsHash = std::map<h256, BlocksBlooms>; using BlocksBloomsHash = std::unordered_map<h256, BlocksBlooms>;
static const BlockDetails NullBlockDetails; static const BlockDetails NullBlockDetails;
static const BlockLogBlooms NullBlockLogBlooms; static const BlockLogBlooms NullBlockLogBlooms;

2
libethereum/DownloadMan.cpp

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

3
libethereum/DownloadMan.h

@ -143,7 +143,8 @@ public:
return ret; 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); } 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(); } unsigned subCount() const { ReadGuard l(x_subs); return m_subs.size(); }
RangeMask<unsigned> blocksGot() const { ReadGuard l(m_lock); return m_blocksGot; } 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. // Done our chain-get.
clog(NetNote) << "Chain download complete."; clog(NetNote) << "Chain download complete.";
// 1/100th for each useful block hash. // 1/100th for each useful block hash.
_who->addRating(m_man.chain().size() / 100); _who->addRating(m_man.chainSize() / 100);
m_man.reset(); m_man.reset();
} }
else if (_who->isSyncing()) 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 GetTransactionsPacket: break; // DEPRECATED.
case TransactionsPacket: case TransactionsPacket:
{ {
clog(NetAllDetail) << "Transactions (" << dec << _r.itemCount() << "entries)"; unsigned itemCount = _r.itemCount();
clog(NetAllDetail) << "Transactions (" << dec << itemCount << "entries)";
Guard l(x_knownTransactions); 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()); auto h = sha3(_r[i].data());
m_knownTransactions.insert(h); m_knownTransactions.insert(h);
@ -373,21 +374,22 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
} }
case BlockHashesPacket: 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) if (m_asking != Asking::Hashes)
{ {
cwarn << "Peer giving us hashes when we didn't ask for them."; cwarn << "Peer giving us hashes when we didn't ask for them.";
break; break;
} }
if (_r.itemCount() == 0) if (itemCount == 0)
{ {
transition(Asking::Blocks); transition(Asking::Blocks);
return true; return true;
} }
unsigned knowns = 0; unsigned knowns = 0;
unsigned unknowns = 0; unsigned unknowns = 0;
for (unsigned i = 0; i < _r.itemCount(); ++i) for (unsigned i = 0; i < itemCount; ++i)
{ {
addRating(1); addRating(1);
auto h = _r[i].toHash<h256>(); auto h = _r[i].toHash<h256>();
@ -454,12 +456,13 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
} }
case BlocksPacket: 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) if (m_asking != Asking::Blocks)
clog(NetWarn) << "Unexpected Blocks received!"; clog(NetWarn) << "Unexpected Blocks received!";
if (_r.itemCount() == 0) if (itemCount == 0)
{ {
// Got to this peer's latest block - just give up. // Got to this peer's latest block - just give up.
transition(Asking::Nothing); transition(Asking::Nothing);
@ -472,7 +475,7 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
unsigned got = 0; unsigned got = 0;
unsigned repeated = 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()); auto h = BlockInfo::headerHash(_r[i].data());
if (m_sub.noteBlock(h)) if (m_sub.noteBlock(h))

Loading…
Cancel
Save