Browse Source

Merge pull request #2489 from arkpar/win-perf

Performance optimizations for msvc build
cl-refactor
Gav Wood 10 years ago
parent
commit
30ef07ccac
  1. 6
      CMakeLists.txt
  2. 6
      libdevcrypto/CMakeLists.txt
  3. 2
      libethcore/EthashCPUMiner.cpp
  4. 37
      libethereum/BlockChain.cpp
  5. 14
      libethereum/BlockChain.h
  6. 2
      libethereum/BlockDetails.h
  7. 2
      libethereum/BlockQueue.cpp
  8. 2
      libethereum/BlockQueue.h
  9. 56
      libethereum/DownloadMan.cpp
  10. 104
      libethereum/DownloadMan.h
  11. 1
      libethereum/TransactionQueue.cpp
  12. 4
      test/CMakeLists.txt

6
CMakeLists.txt

@ -405,10 +405,8 @@ if (JSCONSOLE)
add_subdirectory(ethconsole) add_subdirectory(ethconsole)
endif () endif ()
if (NOT WIN32) add_definitions(-DETH_HAVE_SECP256K1)
add_definitions(-DETH_HAVE_SECP256K1) add_subdirectory(secp256k1)
add_subdirectory(secp256k1)
endif ()
add_subdirectory(libscrypt) add_subdirectory(libscrypt)
add_subdirectory(libdevcrypto) add_subdirectory(libdevcrypto)

6
libdevcrypto/CMakeLists.txt

@ -24,10 +24,8 @@ target_link_libraries(${EXECUTABLE} ${DB_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LIBRARIES})
target_link_libraries(${EXECUTABLE} scrypt) target_link_libraries(${EXECUTABLE} scrypt)
target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} devcore)
if (NOT WIN32) add_definitions(-DETH_HAVE_SECP256K1)
add_definitions(-DETH_HAVE_SECP256K1) target_link_libraries(${EXECUTABLE} secp256k1)
target_link_libraries(${EXECUTABLE} secp256k1)
endif ()
install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} )

2
libethcore/EthashCPUMiner.cpp

@ -35,6 +35,7 @@ using namespace eth;
unsigned EthashCPUMiner::s_numInstances = 0; unsigned EthashCPUMiner::s_numInstances = 0;
#if ETH_CPUID || !ETH_TRUE
static string jsonEncode(map<string, string> const& _m) static string jsonEncode(map<string, string> const& _m)
{ {
string ret = "{"; string ret = "{";
@ -50,6 +51,7 @@ static string jsonEncode(map<string, string> const& _m)
return ret + "}"; return ret + "}";
} }
#endif
void EthashCPUMiner::workLoop() void EthashCPUMiner::workLoop()
{ {

37
libethereum/BlockChain.cpp

@ -85,15 +85,34 @@ std::ostream& dev::eth::operator<<(std::ostream& _out, BlockChain const& _bc)
ldb::Slice dev::eth::toSlice(h256 const& _h, unsigned _sub) ldb::Slice dev::eth::toSlice(h256 const& _h, unsigned _sub)
{ {
#if ALL_COMPILERS_ARE_CPP11_COMPLIANT #if ALL_COMPILERS_ARE_CPP11_COMPLIANT
static thread_local h256 h = _h ^ sha3(h256(u256(_sub))); static thread_local FixedHash<33> h = _h;
return ldb::Slice((char const*)&h, 32); h[32] = (uint8_t)_sub;
return (ldb::Slice)h.ref();
#else #else
static boost::thread_specific_ptr<FixedHash<33>> t_h; static boost::thread_specific_ptr<FixedHash<33>> t_h;
if (!t_h.get()) if (!t_h.get())
t_h.reset(new FixedHash<33>); t_h.reset(new FixedHash<33>);
*t_h = FixedHash<33>(_h); *t_h = FixedHash<33>(_h);
(*t_h)[32] = (uint8_t)_sub; (*t_h)[32] = (uint8_t)_sub;
return (ldb::Slice)t_h->ref();//(char const*)t_h.get(), 32); return (ldb::Slice)t_h->ref();
#endif //ALL_COMPILERS_ARE_CPP11_COMPLIANT
}
ldb::Slice dev::eth::toSlice(uint64_t _n, unsigned _sub)
{
#if ALL_COMPILERS_ARE_CPP11_COMPLIANT
static thread_local FixedHash<33> h;
toBigEndian(_n, bytesRef(h.data() + 24, 8));
h[32] = (uint8_t)_sub;
return (ldb::Slice)h.ref();
#else
static boost::thread_specific_ptr<FixedHash<33>> t_h;
if (!t_h.get())
t_h.reset(new FixedHash<33>);
bytesRef ref(t_h->data() + 24, 8);
toBigEndian(_n, ref);
(*t_h)[32] = (uint8_t)_sub;
return (ldb::Slice)t_h->ref();
#endif #endif
} }
@ -289,7 +308,7 @@ void BlockChain::rebuild(std::string const& _path, std::function<void(unsigned,
} }
try try
{ {
bytes b = block(queryExtras<BlockHash, ExtraBlockHash>(h256(u256(d)), m_blockHashes, x_blockHashes, NullBlockHash, oldExtrasDB).value); bytes b = block(queryExtras<BlockHash, uint64_t, ExtraBlockHash>(d, m_blockHashes, x_blockHashes, NullBlockHash, oldExtrasDB).value);
BlockInfo bi(&b); BlockInfo bi(&b);
if (_prepPoW) if (_prepPoW)
@ -359,7 +378,8 @@ tuple<ImportRoute, bool, unsigned> BlockChain::sync(BlockQueue& _bq, OverlayDB c
r = import(block.verified, _stateDB, ImportRequirements::Everything & ~ImportRequirements::ValidSeal & ~ImportRequirements::CheckUncles); r = import(block.verified, _stateDB, ImportRequirements::Everything & ~ImportRequirements::ValidSeal & ~ImportRequirements::CheckUncles);
fresh += r.liveBlocks; fresh += r.liveBlocks;
dead += r.deadBlocks; dead += r.deadBlocks;
goodTransactions += r.goodTranactions; goodTransactions.reserve(goodTransactions.size() + r.goodTranactions.size());
std::move(std::begin(r.goodTranactions), std::end(r.goodTranactions), std::back_inserter(goodTransactions));
++count; ++count;
} }
catch (dev::eth::UnknownParent) catch (dev::eth::UnknownParent)
@ -607,7 +627,7 @@ ImportRoute BlockChain::import(VerifiedBlockRef const& _block, OverlayDB const&
unsigned n = number(route.front()); unsigned n = number(route.front());
DEV_WRITE_GUARDED(x_blockHashes) DEV_WRITE_GUARDED(x_blockHashes)
for (auto i = route.begin(); i != route.end() && *i != common; ++i, --n) for (auto i = route.begin(); i != route.end() && *i != common; ++i, --n)
m_blockHashes.erase(h256(u256(n))); m_blockHashes.erase(n);
DEV_WRITE_GUARDED(x_transactionAddresses) DEV_WRITE_GUARDED(x_transactionAddresses)
m_transactionAddresses.clear(); // TODO: could perhaps delete them individually? m_transactionAddresses.clear(); // TODO: could perhaps delete them individually?
@ -947,7 +967,7 @@ void BlockChain::noteUsed(h256 const& _h, unsigned _extra) const
m_inUse.insert(id); m_inUse.insert(id);
} }
template <class T> static unsigned getHashSize(unordered_map<h256, T> const& _map) template <class K, class T> static unsigned getHashSize(unordered_map<K, T> const& _map)
{ {
unsigned ret = 0; unsigned ret = 0;
for (auto const& i: _map) for (auto const& i: _map)
@ -1005,9 +1025,6 @@ void BlockChain::garbageCollect(bool _force)
case ExtraDetails: case ExtraDetails:
m_details.erase(id.first); m_details.erase(id.first);
break; break;
case ExtraBlockHash:
m_blockHashes.erase(id.first);
break;
case ExtraReceipts: case ExtraReceipts:
m_receipts.erase(id.first); m_receipts.erase(id.first);
break; break;

14
libethereum/BlockChain.h

@ -72,6 +72,7 @@ struct BlockChainDebug: public LogChannel { static const char* name(); static co
std::unordered_map<Address, Account> const& genesisState(); std::unordered_map<Address, Account> const& genesisState();
ldb::Slice toSlice(h256 const& _h, unsigned _sub = 0); ldb::Slice toSlice(h256 const& _h, unsigned _sub = 0);
ldb::Slice toSlice(uint64_t _n, unsigned _sub = 0);
using BlocksHash = std::unordered_map<h256, bytes>; using BlocksHash = std::unordered_map<h256, bytes>;
using TransactionHashes = h256s; using TransactionHashes = h256s;
@ -168,7 +169,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(_i), m_blockHashes, x_blockHashes, NullBlockHash).value; } h256 numberHash(unsigned _i) const { if (!_i) return genesisHash(); return queryExtras<BlockHash, uint64_t, ExtraBlockHash>(_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()); }
@ -293,7 +294,7 @@ protected:
unsigned open(std::string const& _path, WithExisting _we = WithExisting::Trust); unsigned open(std::string const& _path, WithExisting _we = WithExisting::Trust);
void close(); void close();
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 template<class T, class K, unsigned N> T queryExtras(K const& _h, std::unordered_map<K, T>& _m, boost::shared_mutex& _x, T const& _n, ldb::DB* _extrasDB = nullptr) const
{ {
{ {
ReadGuard l(_x); ReadGuard l(_x);
@ -305,10 +306,7 @@ protected:
std::string s; std::string s;
(_extrasDB ? _extrasDB : m_extrasDB)->Get(m_readOptions, toSlice(_h, N), &s); (_extrasDB ? _extrasDB : m_extrasDB)->Get(m_readOptions, toSlice(_h, N), &s);
if (s.empty()) if (s.empty())
{
// cout << "Not found in DB: " << _h << endl;
return _n; return _n;
}
noteUsed(_h, N); noteUsed(_h, N);
@ -317,6 +315,11 @@ protected:
return ret.first->second; return ret.first->second;
} }
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
{
return queryExtras<T, h256, N>(_h, _m, _x, _n, _extrasDB);
}
void checkConsistency(); void checkConsistency();
/// The caches of the disk DB and their locks. /// The caches of the disk DB and their locks.
@ -340,6 +343,7 @@ protected:
mutable std::deque<std::unordered_set<CacheID>> m_cacheUsage; mutable std::deque<std::unordered_set<CacheID>> m_cacheUsage;
mutable std::unordered_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;
void noteUsed(uint64_t const& _h, unsigned _extra = (unsigned)-1) const { (void)_h; (void)_extra; } // don't note non-hash types
std::chrono::system_clock::time_point m_lastCollection; std::chrono::system_clock::time_point m_lastCollection;
void noteCanonChanged() const { Guard l(x_lastLastHashes); m_lastLastHashes.clear(); } void noteCanonChanged() const { Guard l(x_lastLastHashes); m_lastLastHashes.clear(); }

2
libethereum/BlockDetails.h

@ -114,7 +114,7 @@ using BlockDetailsHash = std::unordered_map<h256, BlockDetails>;
using BlockLogBloomsHash = std::unordered_map<h256, BlockLogBlooms>; using BlockLogBloomsHash = std::unordered_map<h256, BlockLogBlooms>;
using BlockReceiptsHash = std::unordered_map<h256, BlockReceipts>; using BlockReceiptsHash = std::unordered_map<h256, BlockReceipts>;
using TransactionAddressHash = std::unordered_map<h256, TransactionAddress>; using TransactionAddressHash = std::unordered_map<h256, TransactionAddress>;
using BlockHashHash = std::unordered_map<h256, BlockHash>; using BlockHashHash = std::unordered_map<uint64_t, BlockHash>;
using BlocksBloomsHash = std::unordered_map<h256, BlocksBlooms>; using BlocksBloomsHash = std::unordered_map<h256, BlocksBlooms>;
static const BlockDetails NullBlockDetails; static const BlockDetails NullBlockDetails;

2
libethereum/BlockQueue.cpp

@ -292,7 +292,7 @@ void BlockQueue::updateBad_WITH_LOCK(h256 const& _bad)
while (moreBad) while (moreBad)
{ {
moreBad = false; moreBad = false;
std::vector<VerifiedBlock> oldVerified; std::deque<VerifiedBlock> oldVerified;
swap(m_verified, oldVerified); swap(m_verified, oldVerified);
for (auto& b: oldVerified) for (auto& b: oldVerified)
if (m_knownBad.count(b.verified.info.parentHash()) || m_knownBad.count(b.verified.info.hash())) if (m_knownBad.count(b.verified.info.parentHash()) || m_knownBad.count(b.verified.info.hash()))

2
libethereum/BlockQueue.h

@ -154,7 +154,7 @@ private:
mutable Mutex m_verification; ///< Mutex that allows writing to m_verified, m_verifying and m_unverified. mutable Mutex m_verification; ///< Mutex that allows writing to m_verified, m_verifying and m_unverified.
std::condition_variable m_moreToVerify; ///< Signaled when m_unverified has a new entry. std::condition_variable m_moreToVerify; ///< Signaled when m_unverified has a new entry.
std::vector<VerifiedBlock> m_verified; ///< List of blocks, in correct order, verified and ready for chain-import. std::deque<VerifiedBlock> m_verified; ///< List of blocks, in correct order, verified and ready for chain-import.
std::deque<VerifiedBlock> m_verifying; ///< List of blocks being verified; as long as the block component (bytes) is empty, it's not finished. std::deque<VerifiedBlock> m_verifying; ///< List of blocks being verified; as long as the block component (bytes) is empty, it's not finished.
std::deque<UnverifiedBlock> m_unverified; ///< List of <block hash, parent hash, block data> in correct order, ready for verification. std::deque<UnverifiedBlock> m_unverified; ///< List of <block hash, parent hash, block data> in correct order, ready for verification.

56
libethereum/DownloadMan.cpp

@ -24,6 +24,8 @@ using namespace std;
using namespace dev; using namespace dev;
using namespace dev::eth; using namespace dev::eth;
size_t const c_maxDownloadAhead = 50000; // Must not be higher than BlockQueue::c_maxUnknownCount
DownloadMan::Overview DownloadMan::overview() const DownloadMan::Overview DownloadMan::overview() const
{ {
ReadGuard l(m_lock); ReadGuard l(m_lock);
@ -63,9 +65,10 @@ h256Hash DownloadSub::nextFetch(unsigned _n)
if (!m_man || m_man->chainEmpty()) if (!m_man || m_man->chainEmpty())
return h256Hash(); return h256Hash();
m_asked = (~(m_man->taken() + m_attempted)).lowest(_n); RangeMask<unsigned> downloaded = m_man->taken(true);
if (m_asked.empty()) m_asked = (~(m_man->taken(false) + m_attempted)).lowest(_n);
m_asked = (~(m_man->taken(true) + m_attempted)).lowest(_n); if (m_asked.empty() || m_asked.lastIn() - downloaded.firstOut() >= c_maxDownloadAhead)
m_asked = (~(downloaded + m_attempted)).lowest(_n);
m_attempted += m_asked; m_attempted += m_asked;
for (auto i: m_asked) for (auto i: m_asked)
{ {
@ -85,50 +88,3 @@ bool DownloadSub::noteBlock(h256 _hash)
m_remaining.erase(_hash); m_remaining.erase(_hash);
return ret; return ret;
} }
HashDownloadSub::HashDownloadSub(HashDownloadMan& _man): m_man(&_man)
{
WriteGuard l(m_man->x_subs);
m_asked = RangeMask<unsigned>(m_man->m_chainStart, m_man->m_chainStart + m_man->m_chainCount);
m_man->m_subs.insert(this);
}
HashDownloadSub::~HashDownloadSub()
{
if (m_man)
{
WriteGuard l(m_man->x_subs);
m_man->m_subs.erase(this);
}
}
void HashDownloadSub::resetFetch()
{
Guard l(m_fetch);
m_remaining = 0;
m_asked = RangeMask<unsigned>(m_man->m_chainStart, m_man->m_chainStart + m_man->m_chainCount);
}
unsigned HashDownloadSub::nextFetch(unsigned _n)
{
Guard l(m_fetch);
m_asked = RangeMask<unsigned>(m_man->m_chainStart, m_man->m_chainStart + m_man->m_chainCount);
if (!m_man || m_man->chainEmpty())
return 0;
m_asked = (~(m_man->taken())).lowest(_n);
if (m_asked.empty())
m_asked = (~(m_man->taken(true))).lowest(_n);
return *m_asked.begin();
}
void HashDownloadSub::noteHash(unsigned _index, unsigned _size)
{
Guard l(m_fetch);
if (m_man)
for(unsigned i = _index; i < _index + _size; ++i)
if (i >= m_man->m_got.all().first && i < m_man->m_got.all().second)
m_man->m_got += i;
}

104
libethereum/DownloadMan.h

@ -170,110 +170,6 @@ private:
std::unordered_set<DownloadSub*> m_subs; std::unordered_set<DownloadSub*> m_subs;
}; };
class HashDownloadMan;
class HashDownloadSub
{
friend class HashDownloadMan;
public:
HashDownloadSub(HashDownloadMan& _man);
~HashDownloadSub();
/// Finished last fetch - grab the next hash index to download
unsigned nextFetch(unsigned _n);
/// Note that we've received a particular hash range.
void noteHash(unsigned _index, unsigned count);
/// Nothing doing here.
void doneFetch() { resetFetch(); }
bool askedContains(unsigned _i) const { Guard l(m_fetch); return m_asked.contains(_i); }
RangeMask<unsigned> const& asked() const { return m_asked; }
private:
void resetFetch(); // Called by DownloadMan when we need to reset the download.
HashDownloadMan* m_man = nullptr;
mutable Mutex m_fetch;
unsigned m_remaining;
RangeMask<unsigned> m_asked;
};
class HashDownloadMan
{
friend class HashDownloadSub;
public:
~HashDownloadMan()
{
for (auto i: m_subs)
i->m_man = nullptr;
}
void resetToRange(unsigned _start, unsigned _count)
{
{
ReadGuard l(x_subs);
for (auto i: m_subs)
i->resetFetch();
}
WriteGuard l(m_lock);
m_chainStart = _start;
m_chainCount = _count;
m_got += RangeMask<unsigned>(_start, _start + _count);
{
ReadGuard l(x_subs);
for (auto i: m_subs)
i->resetFetch();
}
}
void reset(unsigned _start)
{
WriteGuard l(m_lock);
m_chainStart = _start;
m_chainCount = 0;
m_got = RangeMask<unsigned>(_start, _start);
}
RangeMask<unsigned> taken(bool _desperate = false) const
{
ReadGuard l(m_lock);
auto ret = m_got;
if (!_desperate)
{
ReadGuard l(x_subs);
for (auto i: m_subs)
ret += i->m_asked;
}
return ret;
}
bool isComplete() const
{
ReadGuard l(m_lock);
return m_got.full();
}
size_t chainSize() const { ReadGuard l(m_lock); return m_chainCount; }
size_t chainEmpty() const { ReadGuard l(m_lock); return m_chainCount == 0; }
void foreachSub(std::function<void(HashDownloadSub 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> hashesGot() const { ReadGuard l(m_lock); return m_got; }
private:
mutable SharedMutex m_lock;
unsigned m_chainStart = 0;
unsigned m_chainCount = 0;
RangeMask<unsigned> m_got;
mutable SharedMutex x_subs;
std::unordered_set<HashDownloadSub*> m_subs;
};
} }
} }

1
libethereum/TransactionQueue.cpp

@ -107,6 +107,7 @@ ImportResult TransactionQueue::import(Transaction const& _transaction, IfDropped
return ir; return ir;
{ {
_transaction.safeSender(); // Perform EC recovery outside of the write lock
UpgradeGuard ul(l); UpgradeGuard ul(l);
ret = manageImport_WITH_LOCK(h, _transaction); ret = manageImport_WITH_LOCK(h, _transaction);
} }

4
test/CMakeLists.txt

@ -75,9 +75,7 @@ target_link_libraries(testeth ${CURL_LIBRARIES})
target_link_libraries(testeth ${CRYPTOPP_LIBRARIES}) target_link_libraries(testeth ${CRYPTOPP_LIBRARIES})
target_link_libraries(testeth ethereum) target_link_libraries(testeth ethereum)
target_link_libraries(testeth ethcore) target_link_libraries(testeth ethcore)
if (NOT WIN32) target_link_libraries(testeth secp256k1)
target_link_libraries(testeth secp256k1)
endif()
if (JSCONSOLE) if (JSCONSOLE)
target_link_libraries(testeth jsengine) target_link_libraries(testeth jsengine)

Loading…
Cancel
Save