diff --git a/src/ripple/app/main/Application.cpp b/src/ripple/app/main/Application.cpp index 4440d2030..870734fd7 100644 --- a/src/ripple/app/main/Application.cpp +++ b/src/ripple/app/main/Application.cpp @@ -852,6 +852,7 @@ public: mValidations->flush (); + RippleAddress::clearCache (); stopped (); } diff --git a/src/ripple/protocol/RippleAddress.h b/src/ripple/protocol/RippleAddress.h index 86f0957ed..49959dccc 100644 --- a/src/ripple/protocol/RippleAddress.h +++ b/src/ripple/protocol/RippleAddress.h @@ -67,6 +67,8 @@ public: void clear (); bool isSet () const; + static void clearCache (); + // // Node Public - Also used for Validators // diff --git a/src/ripple/protocol/impl/RippleAddress.cpp b/src/ripple/protocol/impl/RippleAddress.cpp index bca807888..1a20b3630 100644 --- a/src/ripple/protocol/impl/RippleAddress.cpp +++ b/src/ripple/protocol/impl/RippleAddress.cpp @@ -330,9 +330,17 @@ Account RippleAddress::getAccountID () const typedef std::mutex StaticLockType; typedef std::lock_guard StaticScopedLockType; -static StaticLockType s_lock; -static hash_map< Blob , std::string > rncMap; +static StaticLockType s_lock; +static hash_map rncMapOld, rncMapNew; + +void RippleAddress::clearCache () +{ + StaticScopedLockType sl (s_lock); + + rncMapOld.clear (); + rncMapNew.clear (); +} std::string RippleAddress::humanAccountID () const { @@ -343,21 +351,42 @@ std::string RippleAddress::humanAccountID () const case VER_ACCOUNT_ID: { - StaticScopedLockType sl (s_lock); + std::string ret; - auto it = rncMap.find (vchData); + { + StaticScopedLockType sl (s_lock); - if (it != rncMap.end ()) - return it->second; + auto it = rncMapNew.find (vchData); - // VFALCO NOTE Why do we throw everything out? We could keep two maps - // here, switch back and forth keep one of them full and clear the - // other on a swap - but always check both maps for cache hits. - // - if (rncMap.size () > 250000) - rncMap.clear (); + if (it != rncMapNew.end ()) + { + // Found in new map, nothing to do + ret = it->second; + } + else + { + it = rncMapOld.find (vchData); - return rncMap[vchData] = ToString (); + if (it != rncMapOld.end ()) + { + ret = it->second; + rncMapOld.erase (it); + } + else + ret = ToString (); + + if (rncMapNew.size () >= 128000) + { + rncMapOld = std::move (rncMapNew); + rncMapNew.clear (); + rncMapNew.reserve (128000); + } + + rncMapNew[vchData] = ret; + } + } + + return ret; } case VER_ACCOUNT_PUBLIC: