diff --git a/Builds/VisualStudio2012/RippleD.vcxproj b/Builds/VisualStudio2012/RippleD.vcxproj index 5a526bb5a2..9a79dacd89 100644 --- a/Builds/VisualStudio2012/RippleD.vcxproj +++ b/Builds/VisualStudio2012/RippleD.vcxproj @@ -1511,6 +1511,7 @@ + diff --git a/Builds/VisualStudio2012/RippleD.vcxproj.filters b/Builds/VisualStudio2012/RippleD.vcxproj.filters index 95bf06a7da..cbc15ab178 100644 --- a/Builds/VisualStudio2012/RippleD.vcxproj.filters +++ b/Builds/VisualStudio2012/RippleD.vcxproj.filters @@ -1688,6 +1688,9 @@ [1] Ripple\ripple_app\boost + + [1] Ripple\ripple_basics\utility + diff --git a/modules/ripple_app/ledger/Ledger.cpp b/modules/ripple_app/ledger/Ledger.cpp index ce282deab4..755c76722f 100644 --- a/modules/ripple_app/ledger/Ledger.cpp +++ b/modules/ripple_app/ledger/Ledger.cpp @@ -174,38 +174,18 @@ Ledger::Ledger (const std::string& rawLedger, bool hasPrefix) : Ledger::~Ledger () { - double txDeleteSeconds = 0; - + if (mTransactionMap) { - int64 const startTime (Time::getHighResolutionTicks ()); - - mTransactionMap.reset (); - - txDeleteSeconds = Time::highResolutionTicksToSeconds ( - Time::getHighResolutionTicks () - startTime); + logTimedDestroy (mTransactionMap, + String ("mTransactionMap with ") + + String::fromNumber (mTransactionMap->size ()) + " items"); } - double acctDeleteSeconds = 0; - + if (mAccountStateMap) { - int64 const startTime (Time::getHighResolutionTicks ()); - - mAccountStateMap.reset (); - - acctDeleteSeconds = Time::highResolutionTicksToSeconds ( - Time::getHighResolutionTicks () - startTime); - } - - if (txDeleteSeconds >= 1) - { - WriteLog (lsWARNING, Ledger) << "mTransactionMap took " << - String (txDeleteSeconds, 1) << " seconds to destroy."; - } - - if (acctDeleteSeconds >= 1) - { - WriteLog (lsWARNING, Ledger) << "mAccountStateMap took " << - String (acctDeleteSeconds, 1) << " seconds to destroy."; + logTimedDestroy (mAccountStateMap, + String ("mAccountStateMap with ") + + String::fromNumber (mAccountStateMap->size ()) + " items"); } } diff --git a/modules/ripple_app/shamap/ripple_SHAMap.cpp b/modules/ripple_app/shamap/ripple_SHAMap.cpp index 62dd15ea73..43bc4881d8 100644 --- a/modules/ripple_app/shamap/ripple_SHAMap.cpp +++ b/modules/ripple_app/shamap/ripple_SHAMap.cpp @@ -10,6 +10,28 @@ SETUP_LOG (SHAMap) +SHAMap::~SHAMap () +{ + mState = smsInvalid; + + logTimedDestroy (mTNByID, + String ("mTNByID with ") + + String::fromNumber (mTNByID.size ()) + " items"); + + if (mDirtyNodes) + { + logTimedDestroy (mDirtyNodes, + String ("mDirtyNodes with ") + + String::fromNumber (mDirtyNodes->size ()) + " items"); + } + + if (root) + { + logTimedDestroy (root, + String ("root node")); + } +} + void SHAMapNode::setMHash () const { using namespace std; diff --git a/modules/ripple_app/shamap/ripple_SHAMap.h b/modules/ripple_app/shamap/ripple_SHAMap.h index 8a417b2b43..e873080493 100644 --- a/modules/ripple_app/shamap/ripple_SHAMap.h +++ b/modules/ripple_app/shamap/ripple_SHAMap.h @@ -34,9 +34,11 @@ public: explicit SHAMap (SHAMapType t, uint32 seq = 1); SHAMap (SHAMapType t, uint256 const & hash); - ~SHAMap () + ~SHAMap (); + + std::size_t size () const noexcept { - mState = smsInvalid; + return mTNByID.size (); } // Returns a new map that's a snapshot of this one. Force CoW diff --git a/modules/ripple_basics/ripple_basics.h b/modules/ripple_basics/ripple_basics.h index be3d94da28..72526365c9 100644 --- a/modules/ripple_basics/ripple_basics.h +++ b/modules/ripple_basics/ripple_basics.h @@ -90,6 +90,7 @@ using namespace beast; #include "utility/ripple_Sustain.h" #include "utility/ripple_ThreadName.h" #include "utility/ripple_Time.h" +#include "utility/ripple_TimedDestroy.h" #include "utility/ripple_UptimeTimer.h" #include "types/ripple_UInt256.h" diff --git a/modules/ripple_basics/utility/ripple_TimedDestroy.h b/modules/ripple_basics/utility/ripple_TimedDestroy.h new file mode 100644 index 0000000000..4ac0deb5e2 --- /dev/null +++ b/modules/ripple_basics/utility/ripple_TimedDestroy.h @@ -0,0 +1,90 @@ +//------------------------------------------------------------------------------ +/* + Copyright (c) 2011-2013, OpenCoin, Inc. +*/ +//============================================================================== + +#ifndef RIPPLE_TIMEDDESTROY_H_INCLUDED +#define RIPPLE_TIMEDDESTROY_H_INCLUDED + +namespace detail +{ + +/** Template class that performs destruction of an object. + Default implementation simply calls delete +*/ +template +struct Destroyer +{ + static void destroy (Object& object) + { + delete &object; + } +}; + +/** Specialization for boost::shared_ptr. +*/ +template +struct Destroyer > +{ + static void destroy (boost::shared_ptr & p) + { + p.reset (); + } +}; + +/** Specialization for boost::unordered_map +*/ +template +struct Destroyer > +{ + static void destroy (boost::unordered_map & v) + { + v.clear (); + } +}; + + +} + +//------------------------------------------------------------------------------ + +/** Measure the time required to destroy an object. +*/ + +template +double timedDestroy (Object& object) +{ + int64 const startTime (Time::getHighResolutionTicks ()); + + detail::Destroyer ::destroy (object); + + return Time::highResolutionTicksToSeconds ( + Time::getHighResolutionTicks () - startTime); +} + +/** Log the destruction of an object if the time exceeds a threshold. +*/ +template +void logTimedDestroy ( + Object& object, String objectDescription, double thresholdSeconds = 1) +{ + double seconds = timedDestroy (object); + + if (seconds > thresholdSeconds) + { + LogSeverity const severity = lsWARNING; + + if (seconds >= 10) + seconds = std::floor (seconds + 0.5); + else + seconds = static_cast ((seconds * 10 + 0.5) / 10); + + Log (severity, LogPartition::get ()) << + objectDescription << " took "<< + String (seconds) << + " seconds to destroy"; + } +} + +#endif