diff --git a/src/cpp/ripple/AcceptedLedger.h b/src/cpp/ripple/AcceptedLedger.h index f8de687399..25adc64f86 100644 --- a/src/cpp/ripple/AcceptedLedger.h +++ b/src/cpp/ripple/AcceptedLedger.h @@ -70,6 +70,8 @@ public: int getLedgerSeq() const { return mLedger->getLedgerSeq(); } int getTxnCount() const { return mMap.size(); } + static float getCacheHitRate() { return ALCache.getHitRate(); } + ALTransaction::pointer getTxn(int) const; }; diff --git a/src/cpp/ripple/HashedObject.h b/src/cpp/ripple/HashedObject.h index cfc712f131..7c2ac27f16 100644 --- a/src/cpp/ripple/HashedObject.h +++ b/src/cpp/ripple/HashedObject.h @@ -65,7 +65,9 @@ public: HashedObjectStore(int cacheSize, int cacheAge); - bool isLevelDB() { return mLevelDB; } + bool isLevelDB() { return mLevelDB; } + + float getCacheHitRate() { return mCache.getHitRate(); } bool store(HashedObjectType type, uint32 index, const std::vector& data, const uint256& hash) diff --git a/src/cpp/ripple/LedgerHistory.h b/src/cpp/ripple/LedgerHistory.h index 9ee0ed9e87..cfb9239c4e 100644 --- a/src/cpp/ripple/LedgerHistory.h +++ b/src/cpp/ripple/LedgerHistory.h @@ -15,6 +15,7 @@ public: void addLedger(Ledger::pointer ledger); void addAcceptedLedger(Ledger::pointer ledger, bool fromConsensus); + float getCacheHitRate() { return mLedgersByHash.getHitRate(); } uint256 getLedgerHash(uint32 index); Ledger::pointer getLedgerBySeq(uint32 index); Ledger::pointer getLedgerByHash(const uint256& hash); diff --git a/src/cpp/ripple/LedgerMaster.h b/src/cpp/ripple/LedgerMaster.h index dddffaa42e..33b6344934 100644 --- a/src/cpp/ripple/LedgerMaster.h +++ b/src/cpp/ripple/LedgerMaster.h @@ -157,8 +157,9 @@ public: void resumeAcquiring(); - void tune(int size, int age) { mLedgerHistory.tune(size, age); } - void sweep(void) { mLedgerHistory.sweep(); } + void tune(int size, int age) { mLedgerHistory.tune(size, age); } + void sweep() { mLedgerHistory.sweep(); } + float getCacheHitRate() { return mLedgerHistory.getCacheHitRate(); } void addValidateCallback(callback& c) { mOnValidate.push_back(c); } diff --git a/src/cpp/ripple/RPCHandler.cpp b/src/cpp/ripple/RPCHandler.cpp index 0ec133cf74..cf94b00993 100644 --- a/src/cpp/ripple/RPCHandler.cpp +++ b/src/cpp/ripple/RPCHandler.cpp @@ -1071,9 +1071,6 @@ Json::Value RPCHandler::doAccountLines(Json::Value jvRequest, int& cost, ScopedL { jvResult["account"] = raAccount.humanAccountID(); - // XXX This is wrong, we do access the current ledger and do need to worry about changes. - // We access a committed ledger and need not worry about changes. - AccountItems rippleLines(raAccount.getAccountID(), lpLedger, AccountItem::pointer(new RippleState())); Json::Value& jsonLines = (jvResult["lines"] = Json::arrayValue); @@ -1083,9 +1080,9 @@ Json::Value RPCHandler::doAccountLines(Json::Value jvRequest, int& cost, ScopedL if (!raPeer.isValid() || raPeer.getAccountID() == line->getAccountIDPeer()) { - STAmount saBalance = line->getBalance(); - STAmount saLimit = line->getLimit(); - STAmount saLimitPeer = line->getLimitPeer(); + const STAmount& saBalance = line->getBalance(); + const STAmount& saLimit = line->getLimit(); + const STAmount& saLimitPeer = line->getLimitPeer(); Json::Value& jPeer = jsonLines.append(Json::objectValue); @@ -2307,6 +2304,11 @@ Json::Value RPCHandler::doGetCounts(Json::Value jvRequest, int& cost, ScopedLock ret["write_load"] = theApp->getHashedObjectStore().getWriteLoad(); + ret["SLE_hit_rate"] = theApp->getSLECache().getHitRate(); + ret["node_hit_rate"] = theApp->getHashedObjectStore().getCacheHitRate(); + ret["ledger_hit_rate"] = theApp->getLedgerMaster().getCacheHitRate(); + ret["AL_hit_rate"] = AcceptedLedger::getCacheHitRate(); + std::string uptime; int s = upTime(); textTime(uptime, s, "year", 365*24*60*60); @@ -2610,6 +2612,7 @@ Json::Value RPCHandler::lookupLedger(Json::Value jvRequest, Ledger::pointer& lpL case LEDGER_CURRENT: lpLedger = mNetOps->getCurrentSnapshot(); iLedgerIndex = lpLedger->getLedgerSeq(); + assert(lpLedger->isImmutable() && !lpLedger->isClosed()); break; case LEDGER_CLOSED: diff --git a/src/cpp/ripple/RippleAddress.cpp b/src/cpp/ripple/RippleAddress.cpp index 5914c115b6..4c01574225 100644 --- a/src/cpp/ripple/RippleAddress.cpp +++ b/src/cpp/ripple/RippleAddress.cpp @@ -35,11 +35,6 @@ RippleAddress::RippleAddress() : mIsValid(false) nVersion = VER_NONE; } -bool RippleAddress::isValid() const -{ - return mIsValid; -} - void RippleAddress::clear() { nVersion = VER_NONE; diff --git a/src/cpp/ripple/RippleAddress.h b/src/cpp/ripple/RippleAddress.h index eb19e60d94..d4f916b4f9 100644 --- a/src/cpp/ripple/RippleAddress.h +++ b/src/cpp/ripple/RippleAddress.h @@ -28,7 +28,7 @@ public: RippleAddress(); // For public and private key, checks if they are legal. - bool isValid() const; + bool isValid() const { return mIsValid; } void clear(); bool isSet() const; diff --git a/src/cpp/ripple/TaggedCache.h b/src/cpp/ripple/TaggedCache.h index f71f135d01..8b05e30e07 100644 --- a/src/cpp/ripple/TaggedCache.h +++ b/src/cpp/ripple/TaggedCache.h @@ -63,16 +63,21 @@ protected: cache_type mCache; // Hold strong reference to recent objects int mLastSweep; + uint64 mHits, mMisses; + public: TaggedCache(const char *name, int size, int age) - : mName(name), mTargetSize(size), mTargetAge(age), mCacheCount(0), mLastSweep(upTime()) { ; } + : mName(name), mTargetSize(size), mTargetAge(age), mCacheCount(0), mLastSweep(upTime()), + mHits(0), mMisses(0) + { ; } int getTargetSize() const; int getTargetAge() const; int getCacheSize(); int getTrackSize(); - int getSweepAge(); + float getHitRate(); + void clearStats(); void setTargetSize(int size); void setTargetAge(int age); @@ -129,6 +134,19 @@ template int TaggedCache::getTra return mCache.size(); } +template float TaggedCache::getHitRate() +{ + boost::recursive_mutex::scoped_lock sl(mLock); + return (static_cast(mHits) * 100) / (1.0f + mHits + mMisses); +} + +template void TaggedCache::clearStats() +{ + boost::recursive_mutex::scoped_lock sl(mLock); + mHits = 0; + mMisses = 0; +} + template void TaggedCache::clear() { boost::recursive_mutex::scoped_lock sl(mLock); @@ -302,20 +320,27 @@ boost::shared_ptr TaggedCache::fetch(const key_type& key) cache_iterator cit = mCache.find(key); if (cit == mCache.end()) + { + ++mMisses; return data_ptr(); + } cache_entry& entry = cit->second; entry.touch(); if (entry.isCached()) + { + ++mHits; return entry.ptr; + } entry.ptr = entry.lock(); if (entry.isCached()) - { + { // independent of cache size, so not counted as a hit ++mCacheCount; return entry.ptr; } mCache.erase(cit); + ++mMisses; return data_ptr(); }