// balb_performancemonitor.h -*-C++-*- // ---------------------------------------------------------------------------- // NOTICE // // This component is not up to date with current BDE coding standards, and // should not be used as an example for new development. // ---------------------------------------------------------------------------- #ifndef INCLUDED_BALB_PERFORMANCEMONITOR #define INCLUDED_BALB_PERFORMANCEMONITOR #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide a mechanism to collect process performance measures. // //@CLASSES: // balb::PerformanceMonitor: monitor process performance // balb::PerformanceMonitor::Statistics: performance stats // balb::PerformanceMonitor::ConstIterator: stats iteration // //@DESCRIPTION: This component provides an application developer the means to // collect and report performance statistics for an arbitrary number of // processes running on the local machine. The 'balb::PerformanceMonitor' // provides the mechanism for doing so, the // 'balb::PerformanceMonitor::Statistics' class holds the data and the // 'balb::PerformanceMonitor::ConstIterator' class is used to iterate over the // data. The following table describes the measures collecting by this // component. Note that all the collected measures are specific to the // monitored process and do not refer to any system-wide measurement. //.. // Measure Identifier Description // ------- ---------- ----------- // User CPU Time e_CPU_TIME_USER Total amount of time spent executing // instructions in user mode. // // System CPU Time e_CPU_TIME_SYSTEM Total amount of time spent executing // instructions in kernel mode. // // CPU Time e_CPU_TIME The sum of User and System CPU times. // // User CPU % e_CPU_UTIL_USER Percentage of elapsed CPU time this // process spent executing instructions // in user mode. // // System CPU % e_CPU_UTIL_SYSTEM Percentage of elapsed CPU time this // process spent executing instructions // in kernel mode. // // CPU % e_CPU_UTIL Sum of User CPU % and System CPU %. // // Resident Size e_RESIDENT_SIZE Number of mega-bytes of physical // memory used by the process. // // Virtual Size e_VIRTUAL_SIZE The size of the heap, in // mega-bytes. This value does not // include the size of the address // space mapped to files (anonymous or // otherwise.) // // Thread Count e_NUM_THREADS Number of threads executing in the // process. // // Page Faults e_NUM_PAGEFAULTS Total number of page faults incurred // throughout the lifetime of the // process. //.. // ///OS-Specific Permissions ///----------------------- // Various OSs might require specific permissions in order to inspect processes // other than the current process. For example, on Darwin, users other than // root can only inspect processes running under the user with which the // current process is running. This error condition will be indicated by a // non-zero return value from 'registerPid'. // ///Unsupported Platform/Compiler mode - Solaris/g++/32-bits ///-------------------------------------------------------- // Note that this component is not supported when building in 32-bit mode // with the g++ compiler on Solaris, due to Solaris's 'procfs.h' header not // supporting that compiler in 32-bit mode. (DRQS 170291732) // ///Iterator Invalidation ///--------------------- // Registration of new pids does not invalidate existing iterators. // Unregistration of a pid invalidates only iterators pointing to the // statistics for the pid being unregistered. Additionally, unregistering a // pid with a 'balb::PerformanceMonitor' object invalidates all references to // 'Statistics' objects retrieved from those iterators. All other iterators // remain valid. // ///Thread Safety ///------------- // The classes 'balb::PerformanceMonitor' and // 'balb::PerformanceMonitory::Statistics', provided by this component, are // both independently fully *thread-safe* (see 'bsldoc_glossary'). However, // 'balb::PerformanceMonitor::ConstIterator' is only *const* *thread-safe*, // meaning it is not safe to access or modify a 'ConstIterator' in one thread // while another thread modifies the same object. As unregistering a pid with // a 'balb::PerformanceMonitor' object invalidates iterators (see {Iterator // Invalidation}), external synchronization is needed if 'unregisterPid' is // called concurrently to iterating over statistics. Also, in a multi-threaded // context, a 'Statistics' object accessed via a reference (or pointer) from // a 'ConstIterator' object may have its statistics updated at any time by a // call to 'collect' or 'resetStatistics' in another thread. If consistent // access is needed to multiple items in a set of statistics, then the user // should copy the statistics object, and then inspect the copy at their // leisure. // // Notice that this component was implemented with particular usage patterns in // mind, which are captured in the usage examples. // ///Usage ///----- // This section illustrates intended use of this component. // ///Example 1: Basic Use of 'balb::PerformanceMonitor' /// - - - - - - - - - - - - - - - - - - - - - - - - - // The following example shows how to monitor the currently executing process // and produce a formatted report of the collected measures after a certain // interval. // // First, we instantiate a scheduler used by the performance monitor to // schedule collection events. //.. // bdlmt::TimerEventScheduler scheduler; // scheduler.start(); //.. // Then, we create the performance monitor, monitoring the current process and // auto-collecting statistics every second. //.. // balb::PerformanceMonitor perfmon(&scheduler, 1.0); // int rc = perfmon.registerPid(0, "perfmon"); // const int pid = bdls::ProcessUtil::getProcessId(); // // assert(0 == rc); // assert(1 == perfmon.numRegisteredPids()); //.. // Next, we print a formatted report of the performance statistics collected // for each pid every 5 seconds for half a minute. Note, that 'Statistics' // object can be simultaneously modified by scheduler callback and accessed via // a 'ConstIterator'. To ensure that the call to 'Statistics::print' outputs // consistent data from a single update of the statistics for this process, we // create a local copy (copy construction is guaranteed to be thread-safe). //.. // for (int i = 0; i < 6; ++i) { // bslmt::ThreadUtil::microSleep(0, 5); // // balb::PerformanceMonitor::ConstIterator it = perfmon.begin(); // const balb::PerformanceMonitor::Statistics stats = *it; // // assert(pid == stats.pid()); // // bsl::cout << "PID = " << stats.pid() << ":\n"; // stats.print(bsl::cout); // } //.. // Finally, we unregister the process and stop the scheduler to cease // collecting statistics for this process. It is safe to call 'unregisterPid' // here, because we don't have any 'ConstIterators' objects or references to // 'Statistics' objects. //.. // rc = perfmon.unregisterPid(pid); // // assert(0 == rc); // assert(0 == perfmon.numRegisteredPids()); // // scheduler.stop(); //.. #include <balscm_version.h> #include <bslmt_readlockguard.h> #include <bslmt_rwmutex.h> #include <bdlmt_timereventscheduler.h> #include <bsls_atomic.h> #include <bdlt_datetime.h> #include <bsls_timeinterval.h> #include <bslma_allocator.h> #include <bslma_usesbslmaallocator.h> #include <bslmf_nestedtraitdeclaration.h> #include <bsls_assert.h> #include <bsls_platform.h> #include <bsls_types.h> #include <bsl_iosfwd.h> #include <bsl_iterator.h> #include <bsl_map.h> #include <bsl_memory.h> #include <bsl_string.h> namespace BloombergLP { namespace balb { // ======================== // class PerformanceMonitor // ======================== class PerformanceMonitor { // Provides a mechanism to collect performance statistics for an arbitrary // number of processes running on the local machine. public: // FRIENDS class Statistics; friend class Statistics; // Grant visibility of private types to 'Statistics'. class ConstIterator; friend class ConstIterator; // Grant visibility of private types to 'ConstIterator'. private: // PRIVATE TYPES // Defines a type alias for the operating system type discovered by the // 'bsls::platform' component. This type alias is used to specifically // select a particular template specialization of the 'Collector' template. #if defined(BSLS_PLATFORM_OS_LINUX) || defined(BSLS_PLATFORM_OS_CYGWIN) typedef bsls::Platform::OsLinux OsType; #elif defined(BSLS_PLATFORM_OS_FREEBSD) typedef bsls::Platform::OsFreeBsd OsType; #elif defined(BSLS_PLATFORM_OS_DARWIN) typedef bsls::Platform::OsDarwin OsType; #elif defined(BSLS_PLATFORM_OS_UNIX) typedef bsls::Platform::OsUnix OsType; #elif defined(BSLS_PLATFORM_OS_WINDOWS) typedef bsls::Platform::OsWindows OsType; #endif template <class PLATFORM> class Collector; // Forward declares a class template for a performance measure // collector for a parameterized 'PLATFORM'. This class template is // never defined. Instead, we define explicit specializations for // supported platforms. Any attempt to compile this component on // unsupported platforms will result in a compile-time error. typedef Collector<OsType> CollectorType; // Defines a type alias for the type that defines the private platform- // specific mechanism used to collect the performance measures for a // pid. typedef bsl::shared_ptr<CollectorType> CollectorPtr; // Defines a type alias for the shared pointer to the platform-specific // mechanism used to collect the performance measures for a pid. typedef bsl::shared_ptr<Statistics> StatisticsPtr; // Defines a type alias for the shared pointer to the platform-specific // mechanism used to collect the performance measures for a pid. typedef bsl::map<int, bsl::pair<StatisticsPtr, CollectorPtr> > PidMap; // Defines a type alias for the map of pids to their collected // statistics and associated platform-specific collector // implementation. // DATA PidMap d_pidMap; // map of pid stats double d_interval; // collection interval bdlmt::TimerEventScheduler *d_scheduler_p; // scheduler of // collection events // (held) bdlmt::TimerEventScheduler::Handle d_clock; // handle to collection // timer mutable bslmt::RWMutex d_mapGuard; // serializes write // access to 'd_pidMap' bslma::Allocator *d_allocator_p; // supplies memory // (held) private: // NOT IMPLEMENTED PerformanceMonitor(const PerformanceMonitor&); PerformanceMonitor& operator=(const PerformanceMonitor&); public: // TYPES enum Measure { // Enumerates the set of performance measures this class is capable of // monitoring. e_CPU_TIME, // CPU time (seconds) e_CPU_TIME_USER, // user CPU time (seconds) e_CPU_TIME_SYSTEM, // system CPU time (seconds) e_CPU_UTIL, // weighted CPU % (user + system) e_CPU_UTIL_USER, // weighted user CPU % e_CPU_UTIL_SYSTEM, // weighted system CPU % e_RESIDENT_SIZE, // number of MBs of physical memory e_NUM_THREADS, // number of threads e_NUM_PAGEFAULTS, // number of pagefaults (major + minor) e_VIRTUAL_SIZE, // number of MBs in the heap e_NUM_MEASURES #ifndef BDE_OMIT_INTERNAL_DEPRECATED , BAEA_CPU_TIME = e_CPU_TIME , BAEA_CPU_TIME_USER = e_CPU_TIME_USER , BAEA_CPU_TIME_SYSTEM = e_CPU_TIME_SYSTEM , BAEA_CPU_UTIL = e_CPU_UTIL , BAEA_CPU_UTIL_USER = e_CPU_UTIL_USER , BAEA_CPU_UTIL_SYSTEM = e_CPU_UTIL_SYSTEM , BAEA_RESIDENT_SIZE = e_RESIDENT_SIZE , BAEA_NUM_THREADS = e_NUM_THREADS , BAEA_NUM_PAGEFAULTS = e_NUM_PAGEFAULTS , BAEA_VIRTUAL_SIZE = e_VIRTUAL_SIZE , BAEA_NUM_MEASURES = e_NUM_MEASURES , CPU_TIME = e_CPU_TIME , CPU_TIME_USER = e_CPU_TIME_USER , CPU_TIME_SYSTEM = e_CPU_TIME_SYSTEM , CPU_UTIL = e_CPU_UTIL , CPU_UTIL_USER = e_CPU_UTIL_USER , CPU_UTIL_SYSTEM = e_CPU_UTIL_SYSTEM , RESIDENT_SIZE = e_RESIDENT_SIZE , NUM_THREADS = e_NUM_THREADS , NUM_PAGEFAULTS = e_NUM_PAGEFAULTS , VIRTUAL_SIZE = e_VIRTUAL_SIZE , NUM_MEASURES = e_NUM_MEASURES #endif // BDE_OMIT_INTERNAL_DEPRECATED }; class Statistics { // Defines the performance statistics collected for a monitored // process. Note that this class is not fully value-semantic. It is // intended to provide a read-only view of a set of collected // performance statistics. // FRIENDS friend class Collector<OsType>; // Grants write-access to the specific 'Collector' instantiation // for the current platform. // DATA int d_pid; // process identifier bsl::string d_description; // process description bdlt::Datetime d_startTimeUtc; // process start time, in UTC time bsls::TimeInterval d_startTime; // process start time, since the system // epoch double d_elapsedTime; // time elapsed since process startup bsls::AtomicInt d_numSamples; // num samples taken double d_lstData[e_NUM_MEASURES]; // latest collected data double d_minData[e_NUM_MEASURES]; // min double d_maxData[e_NUM_MEASURES]; // max double d_totData[e_NUM_MEASURES]; // cumulative mutable bslmt::RWMutex d_guard; // serialize write access private: // NOT IMPLEMENTED Statistics& operator=(const Statistics&); public: // TRAITS BSLMF_NESTED_TRAIT_DECLARATION(Statistics, bslma::UsesBslmaAllocator); // CREATORS explicit Statistics(bslma::Allocator *basicAllocator = 0); // Create an instance of this class. Optionally specify a // 'basicAllocator' used to supply memory. If 'basicAllocator' is // 0, the currently installed default allocator is used. Statistics(const Statistics& original, bslma::Allocator *basicAllocator = 0); // Create a 'Statistics' object aggregating the same statistics // values as the specified 'original' object. Optionally specify a // 'basicAllocator' used to supply memory. If 'basicAllocator' is // 0, the currently installed default allocator is used. // MANIPULATORS void reset(); // Reset the min, max, and average values collected for each // measure. // ACCESSORS double latestValue(Measure measure) const; // Return the latest collected value for the specified 'measure'. double minValue(Measure measure) const; // Return the minimum collected value for the specified 'measure'. double maxValue(Measure measure) const; // Return the maximum collected value for the specified 'measure'. double avgValue(Measure measure) const; // Return the average of the collected values for the specified // 'metric'. int pid() const; // Return the pid for which these statistics were collected. const bsl::string& description() const; // Return the user-supplied description of the process identified // by the result of the 'pid()' function. double elapsedTime() const; // Return the number of seconds (in wall time) that have elapsed // since the startup the process identified by the result of the // 'pid()' function. const bdlt::Datetime& startupTime() const; // Return the startup time in Coordinated Universal Time. void print(bsl::ostream& os) const; // Print all collected statistics to the specified 'os' stream. void print(bsl::ostream& os, Measure measure) const; // Print the specified 'measure' to the specified 'os' stream. void print(bsl::ostream& os, const char *measureIdentifier) const; // Print the specified 'measureIdentifier' to the specified 'os' // stream. The value of 'measureIdentifier' should be a string // literal corresponding to the desired measure enumerator, e.g., // 'e_CPU_TIME'. }; class ConstIterator { // Provide a mechanism that models the "Forward Iterator" concept over // a collection of non-modifiable performance statistics. // FRIENDS friend class PerformanceMonitor; // grant access to the private // constructor // DATA PidMap::const_iterator d_it; // wrapped iterator bslmt::RWMutex *d_mapGuard_p; // serialize access to the map // PRIVATE CREATORS explicit ConstIterator(PidMap::const_iterator it, bslmt::RWMutex *mapGuard); // Create an instance of this class that wraps the specified 'it' // iterator protected by the specified 'mapGuard'. public: // TYPES typedef bsl::forward_iterator_tag iterator_category; // Defines a type alias for the tag type that represents the // iterator concept this class models. typedef Statistics value_type; // Defines a type alias for the type of the result of dereferencing // this iterator. typedef bsl::ptrdiff_t difference_type; // Defines a type alias for the type of the result of the // difference between the addresses of two value types. typedef const Statistics* pointer; // Defines a type alias for a pointer to this iterator's value // type. typedef const Statistics& reference; // Defines a type alias for a reference to this iterator's value // type. // CREATORS ConstIterator(); // Create an instance of this class having an invalid value. // MANIPULATORS ConstIterator& operator++(); // Advance this iterator to refer to the next collection of // statistics for a monitored pid and return a reference to the // modifiable value type of this iterator. If there is no next // collection of statistics, this iterator will be set equal to // 'end()'. The behavior of this function is undefined unless this // iterator is dereferenceable. ConstIterator operator++(int); // Advance this iterator to refer to the next collection of // statistics for a monitored pid and return the iterator pointing // to the previous modifiable value type. If there is no next // collection of statistics, this iterator will be set equal to // 'end()'. The behavior of this function is undefined unless this // iterator is dereferenceable. // ACCESSORS reference operator*() const; // Return a reference to the non-modifiable value type of this // iterator. pointer operator->() const; // Return a reference to the non-modifiable value type of this // iterator. bool operator==(const ConstIterator& rhs) const; // Return 'true' if the specified 'rhs' iterator points to the // same instance of the iterator's value type as "this" iterator, // and 'false' otherwise. The behavior of this function is // undefined unless the 'rhs' iterator and "this" iterator both // iterate over the same collection of Statistics. bool operator!=(const ConstIterator& rhs) const; // Return 'true' if the specified 'rhs' iterator does not point to // the same instance of the iterator's value type as "this" // iterator, and 'false' otherwise. The behavior of this function // is undefined unless the 'rhs' iterator and "this" iterator both // iterate over the same collection of Statistics. }; // TRAITS BSLMF_NESTED_TRAIT_DECLARATION(PerformanceMonitor, bslma::UsesBslmaAllocator); // CREATORS explicit PerformanceMonitor(bslma::Allocator *basicAllocator = 0); // Create an instance of this class to collect performance statistics // on demand (via the 'collect' method). Optionally specify a // 'basicAllocator' used to supply memory. If 'basicAllocator' is 0, // the currently installed default allocator is used. PerformanceMonitor(bdlmt::TimerEventScheduler *scheduler, double interval, bslma::Allocator *basicAllocator = 0); // Create an instance of this class that uses the specified 'scheduler' // to automatically collect performance statistics every specified // 'interval' (specified in seconds). Optionally specify a // 'basicAllocator' used to supply memory. If 'basicAllocator' is 0, // the currently installed default allocator is used. Note that a // non-positive 'interval' value indicates that performance statistics // should *not* be automatically collected--in this case the user is // responsible for manually calling the 'collect' function. ~PerformanceMonitor(); // Destroy this object. // MANIPULATORS int registerPid(int pid, const bsl::string& description); // Register the specified process 'pid' having the specified // user-defined 'description' with this performance monitor. After // registration, performance statistics will be collected for the // 'pid' upon invocation of the 'collect' function. Note that a 'pid' // value of zero is interpreted as the 'pid' of the current process. // Return 0 on success or a non-zero value otherwise. int unregisterPid(int pid); // Unregister the specified process 'pid' from the performance monitor. // After unregistration, to statistics for the 'pid' will be no longer // be available unless the 'pid' is re-registered with the performance // monitor through calling 'registerPid'. Note that a 'pid' value of // zero is interpreted as the 'pid' of the current process. Return // 0 on success or a non-zero value otherwise. void setCollectionInterval(double interval); // Set the specified time 'interval', in seconds, after which // statistics for each registered pid are automatically collected. The // behavior is undefined unless a scheduler was supplied at the // construction of this performance monitor. Note that a non-positive // 'interval' value indicates that performance statistics should not be // automatically collected--in this case the user is responsible for // manually calling the 'collect' function. void collect(); // Collect performance statistics for each registered pid. void resetStatistics(); // Reset the collected min, max, and average values collected for each // measure for each monitored process. // ACCESSORS ConstIterator begin() const; // Return an iterator positioned at the first set of collected // performance statistics. ConstIterator end() const; // Return an iterator that represents the end of the sequence of sets // of collected performance statistics. ConstIterator find(int pid) const; // Return the iterator pointing to the set of collected performance // statistics for the specified 'pid' if 'pid' has been registered with // this performance monitor through the 'registerPid' function, // otherwise return 'end()'. int numRegisteredPids() const; // Return the number of processes registered for statistics collection. }; #if defined(BSLS_PLATFORM_OS_LINUX) || defined(BSLS_PLATFORM_OS_CYGWIN) struct PerformanceMonitor_LinuxProcStatistics { // Describes the fields present in /proc/<pid>/stat. For a complete // description of each field, see 'man proc'. // // Note that sizes of the data fields are defined in terms of scanf(3) // format specifiers, such as %d, %lu or %c. There is no good way to know // if %lu is 32-bit wide or 64-bit, because the code can be built in the // -m32 mode making sizeof(unsigned long)==4 and executed on a 64bit // platform where the kernel thinks that %lu can represent 64-bit wide // integers. Therefore we use 'Uint64' regardless of the build // configuration. // PUBLIC TYPES typedef bsls::Types::Int64 LdType; typedef bsls::Types::Uint64 LuType; typedef bsls::Types::Uint64 LluType; // PUBLIC DATA int d_pid; // process pid bsl::string d_comm; // filename of executable char d_state; // process state int d_ppid; // process's parent pid int d_pgrp; // process group id int d_session; // process session id int d_tty_nr; // the tty used by the process int d_tpgid; // tty owner's group id unsigned int d_flags; // kernel flags LuType d_minflt; // num minor page faults LuType d_cminflt; // num minor page faults - children LuType d_majflt; // num major page faults LuType d_cmajflt; // num major page faults - children LuType d_utime; // num jiffies in user mode LuType d_stime; // num jiffies in kernel mode LdType d_cutime; // num jiffies, user mode, children LdType d_cstime; // num jiffies, kernel mode, children LdType d_priority; // standard nice value, plus fifteen LdType d_nice; // nice value LdType d_numThreads; // number of threads (since Linux 2.6) LdType d_itrealvalue; // num jiffies before next SIGALRM LluType d_starttime; // time in jiffies since system boot LuType d_vsize; // virtual memory size, in bytes LdType d_rss; // resident set size, in pages // Note that subsequent fields present in '/proc/<pid>/stat' are not // required for any collected measures. // CLASS METHOD static int readProcStatString(bsl::string *buffer, int pid); // For the specified process id 'pid', load the contents of the file // '/proc/<pid>/stat' into the specified 'buffer'. Return 0 on success // and a non-zero value otherwise. private: // NOT IMPLEMENTED public: // CREATORS PerformanceMonitor_LinuxProcStatistics(); // Default construct all fields in this object. // PerformanceMonitor_LinuxProcStatistics( // const PerformanceMonitor_LinuxProcStatistics&) = default; // MANIPULATORS // PerformanceMonitor_LinuxProcStatistics& operator=( // const PerformanceMonitor_LinuxProcStatistics& rhs) = default; // Copy all fields of the specified 'rhs' to this object, and return a // reference to it. int parseProcStatString(const bsl::string& procStatString, int pid); // Parse the specified 'procStatString' and populate all the fields in // this 'struct'. Check that the specified 'pid' matches the 'pid' // field in the string. Return 0 on success and a non-zero value // otherwise. }; #endif // ============================================================================ // INLINE DEFINITIONS // ============================================================================ // --------------------------------------- // class PerformanceMonitor::ConstIterator // --------------------------------------- // CREATORS inline PerformanceMonitor::ConstIterator::ConstIterator() : d_it() { } inline PerformanceMonitor::ConstIterator::ConstIterator( PerformanceMonitor::PidMap::const_iterator it, bslmt::RWMutex *mapGuard) : d_it(it) , d_mapGuard_p(mapGuard) { } // ACCESSORS inline PerformanceMonitor::ConstIterator::reference PerformanceMonitor::ConstIterator::operator*() const { bslmt::ReadLockGuard<bslmt::RWMutex> guard(d_mapGuard_p); return *d_it->second.first; } inline PerformanceMonitor::ConstIterator::pointer PerformanceMonitor::ConstIterator::operator->() const { bslmt::ReadLockGuard<bslmt::RWMutex> guard(d_mapGuard_p); return d_it->second.first.get(); } // MANIPULATORS inline PerformanceMonitor::ConstIterator& PerformanceMonitor::ConstIterator::operator++() { bslmt::ReadLockGuard<bslmt::RWMutex> guard(d_mapGuard_p); ++d_it; return *this; } inline PerformanceMonitor::ConstIterator PerformanceMonitor::ConstIterator::operator++(int) { PerformanceMonitor::ConstIterator temp = *this; ++*this; return temp; } // ACCESSORS inline bool PerformanceMonitor::ConstIterator::operator==( const ConstIterator& rhs) const { return d_it == rhs.d_it; } inline bool PerformanceMonitor::ConstIterator::operator!=( const ConstIterator& rhs) const { return d_it != rhs.d_it; } // ------------------------------------ // class PerformanceMonitor::Statistics // ------------------------------------ // ACCESSORS inline double PerformanceMonitor::Statistics::latestValue(Measure measure) const { BSLS_ASSERT_SAFE(measure >= 0 && measure < e_NUM_MEASURES); bslmt::ReadLockGuard<bslmt::RWMutex> guard(&d_guard); return d_lstData[measure]; } inline double PerformanceMonitor::Statistics::minValue(Measure measure) const { BSLS_ASSERT_SAFE(measure >= 0 && measure < e_NUM_MEASURES); bslmt::ReadLockGuard<bslmt::RWMutex> guard(&d_guard); return d_minData[measure]; } inline double PerformanceMonitor::Statistics::maxValue(Measure measure) const { BSLS_ASSERT_SAFE(measure >= 0 && measure < e_NUM_MEASURES); bslmt::ReadLockGuard<bslmt::RWMutex> guard(&d_guard); return d_maxData[measure]; } inline double PerformanceMonitor::Statistics::avgValue(Measure measure) const { BSLS_ASSERT_SAFE(measure >= 0 && measure < e_NUM_MEASURES); bslmt::ReadLockGuard<bslmt::RWMutex> guard(&d_guard); return d_totData[measure] / d_numSamples; } inline int PerformanceMonitor::Statistics::pid() const { return d_pid; } inline const bsl::string& PerformanceMonitor::Statistics::description() const { return d_description; } inline double PerformanceMonitor::Statistics::elapsedTime() const { bslmt::ReadLockGuard<bslmt::RWMutex> guard(&d_guard); return d_elapsedTime; } inline const bdlt::Datetime& PerformanceMonitor::Statistics::startupTime() const { return d_startTimeUtc; } // ------------------------ // class PerformanceMonitor // ------------------------ // ACCESSORS inline PerformanceMonitor::ConstIterator PerformanceMonitor::begin() const { bslmt::ReadLockGuard<bslmt::RWMutex> guard(&d_mapGuard); return ConstIterator(d_pidMap.begin(), &d_mapGuard); } inline PerformanceMonitor::ConstIterator PerformanceMonitor::end() const { bslmt::ReadLockGuard<bslmt::RWMutex> guard(&d_mapGuard); return ConstIterator(d_pidMap.end(), &d_mapGuard); } inline PerformanceMonitor::ConstIterator PerformanceMonitor::find(int pid) const { bslmt::ReadLockGuard<bslmt::RWMutex> guard(&d_mapGuard); return ConstIterator(d_pidMap.find(pid), &d_mapGuard); } inline int PerformanceMonitor::numRegisteredPids() const { bslmt::ReadLockGuard<bslmt::RWMutex> guard(&d_mapGuard); return static_cast<int>(d_pidMap.size()); } } // close package namespace } // close enterprise namespace #endif // ---------------------------------------------------------------------------- // Copyright 2018 Bloomberg Finance L.P. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ----------------------------- END-OF-FILE ----------------------------------