BDE 4.39.x Production Release
Loading...
Searching...
No Matches
balb_performancemonitor.h
Go to the documentation of this file.
1/// @file balb_performancemonitor.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// balb_performancemonitor.h -*-C++-*-
8#ifndef INCLUDED_BALB_PERFORMANCEMONITOR
9#define INCLUDED_BALB_PERFORMANCEMONITOR
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup balb_performancemonitor balb_performancemonitor
15/// @brief Provide a mechanism to collect process performance measures.
16/// @addtogroup bal
17/// @{
18/// @addtogroup balb
19/// @{
20/// @addtogroup balb_performancemonitor
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#balb_performancemonitor-purpose"> Purpose</a>
25/// * <a href="#balb_performancemonitor-classes"> Classes </a>
26/// * <a href="#balb_performancemonitor-description"> Description </a>
27/// * <a href="#balb_performancemonitor-os-specific-permissions"> OS-Specific Permissions </a>
28/// * <a href="#balb_performancemonitor-unsupported-platformcompiler-mode---solarisg-1132-bits"> Unsupported PlatformCompiler mode - Solarisg++ <= 1132-bits </a>
29/// * <a href="#balb_performancemonitor-iterator-invalidation"> Iterator Invalidation </a>
30/// * <a href="#balb_performancemonitor-thread-safety"> Thread Safety </a>
31/// * <a href="#balb_performancemonitor-usage"> Usage </a>
32/// * <a href="#balb_performancemonitor-example-1-basic-use-of-balb-performancemonitor"> Example 1: Basic Use of balb::PerformanceMonitor </a>
33///
34/// # Purpose {#balb_performancemonitor-purpose}
35/// Provide a mechanism to collect process performance measures.
36///
37/// # Classes {#balb_performancemonitor-classes}
38///
39/// - balb::PerformanceMonitor: monitor process performance
40/// - balb::PerformanceMonitor::Statistics: performance stats
41/// - balb::PerformanceMonitor::ConstIterator: stats iteration
42///
43/// # Description {#balb_performancemonitor-description}
44/// This component provides an application developer the means to
45/// collect and report performance statistics for an arbitrary number of
46/// processes running on the local machine. The `balb::PerformanceMonitor`
47/// provides the mechanism for doing so, the
48/// `balb::PerformanceMonitor::Statistics` class holds the data and the
49/// `balb::PerformanceMonitor::ConstIterator` class is used to iterate over the
50/// data. The following table describes the measures collecting by this
51/// component. Note that all the collected measures are specific to the
52/// monitored process and do not refer to any system-wide measurement.
53/// @code
54/// Measure Identifier Description
55/// ------- ---------- -----------
56/// User CPU Time e_CPU_TIME_USER Total amount of time spent executing
57/// instructions in user mode.
58///
59/// System CPU Time e_CPU_TIME_SYSTEM Total amount of time spent executing
60/// instructions in kernel mode.
61///
62/// CPU Time e_CPU_TIME The sum of User and System CPU times.
63///
64/// User CPU % e_CPU_UTIL_USER Percentage of elapsed CPU time this
65/// process spent executing instructions
66/// in user mode.
67///
68/// System CPU % e_CPU_UTIL_SYSTEM Percentage of elapsed CPU time this
69/// process spent executing instructions
70/// in kernel mode.
71///
72/// CPU % e_CPU_UTIL Sum of User CPU % and System CPU %.
73///
74/// Resident Size e_RESIDENT_SIZE Number of mega-bytes of physical
75/// memory used by the process.
76///
77/// Virtual Size e_VIRTUAL_SIZE The size of the heap, in
78/// mega-bytes. This value does not
79/// include the size of the address
80/// space mapped to files (anonymous or
81/// otherwise.)
82///
83/// Thread Count e_NUM_THREADS Number of threads executing in the
84/// process.
85///
86/// Page Faults e_NUM_PAGEFAULTS Total number of page faults incurred
87/// throughout the lifetime of the
88/// process.
89/// @endcode
90///
91/// ## OS-Specific Permissions {#balb_performancemonitor-os-specific-permissions}
92///
93///
94/// Various OSs might require specific permissions in order to inspect processes
95/// other than the current process. For example, on Darwin, users other than
96/// root can only inspect processes running under the user with which the
97/// current process is running. This error condition will be indicated by a
98/// non-zero return value from `registerPid`.
99///
100/// ## Unsupported PlatformCompiler mode - Solarisg++ <= 1132-bits {#balb_performancemonitor-unsupported-platformcompiler-mode---solarisg-1132-bits}
101///
102///
103/// Note that this component is not supported when building in 32-bit mode
104/// with the g++ compiler version 11 or below on Solaris, due to Solaris's
105/// `procfs.h` header not supporting that compiler in 32-bit mode.
106/// (DRQS 170291732)
107///
108/// ## Iterator Invalidation {#balb_performancemonitor-iterator-invalidation}
109///
110///
111/// Registration of new pids does not invalidate existing iterators.
112/// Unregistration of a pid invalidates only iterators pointing to the
113/// statistics for the pid being unregistered. Additionally, unregistering a
114/// pid with a `balb::PerformanceMonitor` object invalidates all references to
115/// `Statistics` objects retrieved from those iterators. All other iterators
116/// remain valid.
117///
118/// ## Thread Safety {#balb_performancemonitor-thread-safety}
119///
120///
121/// The classes `balb::PerformanceMonitor` and
122/// `balb::PerformanceMonitor::Statistics`, provided by this component, are
123/// both independently fully *thread-safe* (see @ref bsldoc_glossary ). However,
124/// `balb::PerformanceMonitor::ConstIterator` is only *const* *thread-safe*,
125/// meaning it is not safe to access or modify a `ConstIterator` in one thread
126/// while another thread modifies the same object. As unregistering a pid with
127/// a `balb::PerformanceMonitor` object invalidates iterators (see {Iterator
128/// Invalidation}), external synchronization is needed if `unregisterPid` is
129/// called concurrently to iterating over statistics. Also, in a multi-threaded
130/// context, a `Statistics` object accessed via a reference (or pointer) from
131/// a `ConstIterator` object may have its statistics updated at any time by a
132/// call to `collect` or `resetStatistics` in another thread. If consistent
133/// access is needed to multiple items in a set of statistics, then the user
134/// should copy the statistics object, and then inspect the copy at their
135/// leisure.
136///
137/// Notice that this component was implemented with particular usage patterns in
138/// mind, which are captured in the usage examples.
139///
140/// ## Usage {#balb_performancemonitor-usage}
141///
142///
143/// This section illustrates intended use of this component.
144///
145/// ### Example 1: Basic Use of balb::PerformanceMonitor {#balb_performancemonitor-example-1-basic-use-of-balb-performancemonitor}
146///
147///
148/// The following example shows how to monitor the currently executing process
149/// and produce a formatted report of the collected measures after a certain
150/// interval.
151///
152/// First, we instantiate a scheduler used by the performance monitor to
153/// schedule collection events.
154/// @code
155/// bdlmt::TimerEventScheduler scheduler;
156/// scheduler.start();
157/// @endcode
158/// Then, we create the performance monitor, monitoring the current process and
159/// auto-collecting statistics every second.
160/// @code
161/// balb::PerformanceMonitor perfmon(&scheduler, 1.0);
162/// int rc = perfmon.registerPid(0, "perfmon");
163/// const int pid = bdls::ProcessUtil::getProcessId();
164///
165/// assert(0 == rc);
166/// assert(1 == perfmon.numRegisteredPids());
167/// @endcode
168/// Next, we print a formatted report of the performance statistics collected
169/// for each pid every 5 seconds for half a minute. Note, that `Statistics`
170/// object can be simultaneously modified by scheduler callback and accessed via
171/// a `ConstIterator`. To ensure that the call to `Statistics::print` outputs
172/// consistent data from a single update of the statistics for this process, we
173/// create a local copy (copy construction is guaranteed to be thread-safe).
174/// @code
175/// for (int i = 0; i < 6; ++i) {
176/// bslmt::ThreadUtil::microSleep(0, 5);
177///
178/// balb::PerformanceMonitor::ConstIterator it = perfmon.find(0);
179/// const balb::PerformanceMonitor::Statistics stats = *it;
180///
181/// assert(pid == stats.pid());
182///
183/// bsl::cout << "PID = " << stats.pid() << ":\n";
184/// stats.print(bsl::cout);
185/// }
186/// @endcode
187/// Finally, we unregister the process and stop the scheduler to cease
188/// collecting statistics for this process. It is safe to call `unregisterPid`
189/// here, because we don't have any `ConstIterators` objects or references to
190/// `Statistics` objects.
191/// @code
192/// rc = perfmon.unregisterPid(pid);
193///
194/// assert(0 == rc);
195/// assert(0 == perfmon.numRegisteredPids());
196///
197/// scheduler.stop();
198/// @endcode
199/// @}
200/** @} */
201/** @} */
202
203/** @addtogroup bal
204 * @{
205 */
206/** @addtogroup balb
207 * @{
208 */
209/** @addtogroup balb_performancemonitor
210 * @{
211 */
212
213#include <balscm_version.h>
214
215#ifndef BDE_OMIT_INTERNAL_DEPRECATED
216#include <bsla_deprecated.h>
217#endif
218
220#include <bdls_processutil.h>
221#include <bdlt_datetime.h>
222
223#include <bslma_allocator.h>
226#include <bslmt_readlockguard.h>
227#include <bslmt_rwmutex.h>
228#include <bsls_assert.h>
229#include <bsls_atomic.h>
230#include <bsls_platform.h>
231#include <bsls_timeinterval.h>
232#include <bsls_types.h>
233
234#include <bsl_iosfwd.h>
235#include <bsl_iterator.h>
236#include <bsl_map.h>
237#include <bsl_memory.h>
238#include <bsl_string.h>
239
240
241namespace balb {
242
243 // ========================
244 // class PerformanceMonitor
245 // ========================
246
247/// Provides a mechanism to collect performance statistics for an arbitrary
248/// number of processes running on the local machine.
249///
250/// See @ref balb_performancemonitor
252
253 public:
254 // TYPES
255
256 // Enumerates the set of performance measures this class is capable of
257 // monitoring. Note that CPU utilization measures are calculated as a
258 // ratio of CPU time to elapsed time between two consecutive calls to
259 // `collect`, and therefore no value will be available if `collect` has
260 // been called only once. Note that not all measures are supported on all
261 // platforms; for an unsupported measure, the behavior is as if the system
262 // reports a zero value.
263 enum Measure {
264 e_CPU_TIME, // CPU time (seconds)
265 e_CPU_TIME_USER, // user CPU time (seconds)
266 e_CPU_TIME_SYSTEM, // system CPU time (seconds)
267 e_CPU_UTIL, // weighted CPU % (user + system)
268 e_CPU_UTIL_USER, // weighted user CPU %
269 e_CPU_UTIL_SYSTEM, // weighted system CPU %
270 e_RESIDENT_SIZE, // number of MBs of physical memory
271 e_NUM_THREADS, // number of threads
272 e_NUM_PAGEFAULTS, // number of pagefaults (major + minor)
273 e_VIRTUAL_SIZE, // number of MBs in the heap
275#ifndef BDE_OMIT_INTERNAL_DEPRECATED
276 , BAEA_CPU_TIME BSLA_DEPRECATED = e_CPU_TIME
277 , BAEA_CPU_TIME_USER BSLA_DEPRECATED = e_CPU_TIME_USER
278 , BAEA_CPU_TIME_SYSTEM BSLA_DEPRECATED = e_CPU_TIME_SYSTEM
279 , BAEA_CPU_UTIL BSLA_DEPRECATED = e_CPU_UTIL
280 , BAEA_CPU_UTIL_USER BSLA_DEPRECATED = e_CPU_UTIL_USER
281 , BAEA_CPU_UTIL_SYSTEM BSLA_DEPRECATED = e_CPU_UTIL_SYSTEM
282 , BAEA_RESIDENT_SIZE BSLA_DEPRECATED = e_RESIDENT_SIZE
283 , BAEA_NUM_THREADS BSLA_DEPRECATED = e_NUM_THREADS
284 , BAEA_NUM_PAGEFAULTS BSLA_DEPRECATED = e_NUM_PAGEFAULTS
285 , BAEA_VIRTUAL_SIZE BSLA_DEPRECATED = e_VIRTUAL_SIZE
286 , BAEA_NUM_MEASURES BSLA_DEPRECATED = e_NUM_MEASURES
287 , CPU_TIME BSLA_DEPRECATED = e_CPU_TIME
288 , CPU_TIME_USER BSLA_DEPRECATED = e_CPU_TIME_USER
289 , CPU_TIME_SYSTEM BSLA_DEPRECATED = e_CPU_TIME_SYSTEM
290 , CPU_UTIL BSLA_DEPRECATED = e_CPU_UTIL
291 , CPU_UTIL_USER BSLA_DEPRECATED = e_CPU_UTIL_USER
292 , CPU_UTIL_SYSTEM BSLA_DEPRECATED = e_CPU_UTIL_SYSTEM
293 , RESIDENT_SIZE BSLA_DEPRECATED = e_RESIDENT_SIZE
294 , NUM_THREADS BSLA_DEPRECATED = e_NUM_THREADS
295 , NUM_PAGEFAULTS BSLA_DEPRECATED = e_NUM_PAGEFAULTS
296 , VIRTUAL_SIZE BSLA_DEPRECATED = e_VIRTUAL_SIZE
297 , NUM_MEASURES BSLA_DEPRECATED = e_NUM_MEASURES
298#endif // BDE_OMIT_INTERNAL_DEPRECATED
299 };
300
301 // FRIENDS
302 class Statistics;
303 friend class Statistics;
304 // Grant visibility of private types to 'Statistics'.
305
306 class ConstIterator;
307 friend class ConstIterator;
308 // Grant visibility of private types to 'ConstIterator'.
309
310 private:
311 // PRIVATE TYPES
312
313 // Defines a type alias for the operating system type discovered by the
314 // 'bsls::platform' component. This type alias is used to specifically
315 // select a particular template specialization of the 'Collector' template.
316
317#if defined(BSLS_PLATFORM_OS_LINUX) || defined(BSLS_PLATFORM_OS_CYGWIN)
318 typedef bsls::Platform::OsLinux OsType;
319#elif defined(BSLS_PLATFORM_OS_FREEBSD)
320 typedef bsls::Platform::OsFreeBsd OsType;
321#elif defined(BSLS_PLATFORM_OS_DARWIN)
322 typedef bsls::Platform::OsDarwin OsType;
323#elif defined(BSLS_PLATFORM_OS_UNIX)
324 typedef bsls::Platform::OsUnix OsType;
325#elif defined(BSLS_PLATFORM_OS_WINDOWS)
326 typedef bsls::Platform::OsWindows OsType;
327#endif
328
329 /// Forward declares a class template for a performance measure
330 /// collector for a parameterized `PLATFORM`. This class template is
331 /// never defined. Instead, we define explicit specializations for
332 /// supported platforms. Any attempt to compile this component on
333 /// unsupported platforms will result in a compile-time error.
334 template <class PLATFORM>
335 class Collector;
336
337 /// Defines a type alias for the type that defines the private platform-
338 /// specific mechanism used to collect the performance measures for a
339 /// pid.
340 typedef Collector<OsType> CollectorType;
341
342 /// Defines a type alias for the shared pointer to the platform-specific
343 /// mechanism used to collect the performance measures for a pid.
345
346 /// Defines a type alias for the shared pointer to the platform-specific
347 /// mechanism used to collect the performance measures for a pid.
349
350 /// Defines a type alias for the map of pids to their collected
351 /// statistics and associated platform-specific collector
352 /// implementation.
354
355 /// Enumeration used to distinguish rate and non-rate measures. A rate
356 /// measure (i.e. a CPU utilization rate) is calculated by dividing another
357 /// quantity by the elapsed time between two collections.
358 enum MeasureType {
359 e_NON_RATE_MEASURE,
360 e_RATE_MEASURE,
361 e_NUM_MEASURE_TYPES
362 };
363
364 /// This struct is defined in the .cpp file.
365 struct MeasureData;
366
367 // CLASS DATA
368
369 /// This array contains the properties of all measures defined by this
370 /// class.
371 static const MeasureData s_measureData[e_NUM_MEASURES];
372
373 // DATA
374 PidMap d_pidMap; // map of pid stats
375
376 double d_interval; // collection interval
377
378 bdlmt::TimerEventScheduler *d_scheduler_p; // scheduler of
379 // collection events
380 // (held)
381
382 bdlmt::TimerEventScheduler::Handle d_clock; // handle to collection
383 // timer
384
385 mutable bslmt::RWMutex d_mapGuard; // serializes write
386 // access to 'd_pidMap'
387
388 bslma::Allocator *d_allocator_p; // supplies memory
389 // (held)
390
391 private:
392 // NOT IMPLEMENTED
394 PerformanceMonitor& operator=(const PerformanceMonitor&);
395
396 public:
397 // TYPES
398
399 /// Defines the performance statistics collected for a monitored process.
400 ///
401 /// \note Note that this class is not fully value-semantic. It is
402 /// intended to provide a read-only view of a set of collected
403 /// performance statistics.
404 ///
405 /// See @ref balb_performancemonitor
407
408 // FRIENDS
409 friend class Collector<OsType>;
410 // Grants write-access to the specific 'Collector' instantiation
411 // for the current platform.
412
413 // DATA
414 int d_pid;
415 // process identifier
416
417 bsl::string d_description;
418 // process description
419
420 bdlt::Datetime d_startTimeUtc;
421 // process start time, in UTC time
422
423 bsls::TimeInterval d_startTime;
424 // process start time, since the system
425 // epoch
426
427 double d_elapsedTime;
428 // time elapsed since process startup
429
430 int d_numSamples[e_NUM_MEASURE_TYPES];
431 // num samples taken, indexed by measure type
432
433 double d_lstData[e_NUM_MEASURES];
434 // latest collected data
435
436 double d_minData[e_NUM_MEASURES];
437 // min
438
439 double d_maxData[e_NUM_MEASURES];
440 // max
441
442 double d_totData[e_NUM_MEASURES];
443 // cumulative
444
445 mutable bslmt::RWMutex d_guard;
446 // serialize write access
447
448 private:
449 // NOT IMPLEMENTED
450 Statistics& operator=(const Statistics&);
451
452 public:
453 // TRAITS
456
457 // CREATORS
458
459 /// Create an instance of this class. Optionally specify a
460 /// `basicAllocator` used to supply memory. If `basicAllocator` is
461 /// 0, the currently installed default allocator is used.
462 explicit Statistics(bslma::Allocator *basicAllocator = 0);
463
464 /// Create a `Statistics` object aggregating the same statistics
465 /// values as the specified `original` object. Optionally specify a
466 /// `basicAllocator` used to supply memory. If `basicAllocator` is
467 /// 0, the currently installed default allocator is used.
468 Statistics(const Statistics& original,
469 bslma::Allocator *basicAllocator = 0);
470
471 // MANIPULATORS
472
473 /// Reset this object to the state in which no samples have been collected.
474 ///
475 /// \note Note that although this method is public, it can't be
476 /// called directly by users, since `PerformanceMonitor` provides only
477 /// const access to statistics.
478 void reset();
479
480 // ACCESSORS
481
482 /// Return the latest collected value for the specified `measure`, or 0
483 /// if no values are yet available.
484 double latestValue(Measure measure) const;
485
486 /// Return the minimum collected value for the specified `measure`, or
487 /// a large positive value if no values have been collected.
488 double minValue(Measure measure) const;
489
490 /// Return the maximum collected value for the specified `measure`, or
491 /// a large negative value if no values have been collected.
492 double maxValue(Measure measure) const;
493
494 /// Return the average of the collected values for the specified
495 /// `metric`, or an unspecified value if no values have been collected.
496 double avgValue(Measure measure) const;
497
498 /// Return the pid for which these statistics were collected.
499 int pid() const;
500
501 /// Return the user-supplied description of the process identified
502 /// by the result of the `pid()` function.
503 const bsl::string& description() const;
504
505 /// Return the number of seconds (in wall time) that have elapsed
506 /// since the startup the process identified by the result of the
507 /// `pid()` function.
508 double elapsedTime() const;
509
510 /// Return the startup time in Coordinated Universal Time.
511 const bdlt::Datetime& startupTime() const;
512
513 /// Print all collected statistics to the specified `os` stream.
514 void print(bsl::ostream& os) const;
515
516 /// Print the specified `measure` to the specified `os` stream.
517 void print(bsl::ostream& os, Measure measure) const;
518
519 /// Print the specified `measureIdentifier` to the specified `os`
520 /// stream. The value of `measureIdentifier` should be a string
521 /// literal corresponding to the desired measure enumerator, e.g.,
522 /// `e_CPU_TIME`.
523 void print(bsl::ostream& os, const char *measureIdentifier) const;
524 };
525
526 /// Provide a mechanism that models the "Forward Iterator" concept over
527 /// a collection of non-modifiable performance statistics.
528 ///
529 /// See @ref balb_performancemonitor
531
532 // FRIENDS
533 friend class PerformanceMonitor; // grant access to the private
534 // constructor
535
536 // DATA
537 PidMap::const_iterator d_it; // wrapped iterator
538 bslmt::RWMutex *d_mapGuard_p; // serialize access to the map
539
540 // PRIVATE CREATORS
541
542 /// Create an instance of this class that wraps the specified `it`
543 /// iterator protected by the specified `mapGuard`.
545 bslmt::RWMutex *mapGuard);
546
547 public:
548 // TYPES
549
550 /// Defines a type alias for the tag type that represents the
551 /// iterator concept this class models.
552 typedef bsl::forward_iterator_tag iterator_category;
553
554 /// Defines a type alias for the type of the result of dereferencing
555 /// this iterator.
557
558 /// Defines a type alias for the type of the result of the
559 /// difference between the addresses of two value types.
560 typedef bsl::ptrdiff_t difference_type;
561
562 /// Defines a type alias for a pointer to this iterator's value
563 /// type.
564 typedef const Statistics* pointer;
565
566 /// Defines a type alias for a reference to this iterator's value
567 /// type.
568 typedef const Statistics& reference;
569
570 // CREATORS
571
572 /// Create an instance of this class having an invalid value.
574
575 // MANIPULATORS
576
577 /// Advance this iterator to refer to the next collection of
578 /// statistics for a monitored pid and return a reference to the
579 /// modifiable value type of this iterator. If there is no next
580 /// collection of statistics, this iterator will be set equal to
581 /// `end()`. The behavior of this function is undefined unless this
582 /// iterator is dereferenceable.
584
585 /// Advance this iterator to refer to the next collection of
586 /// statistics for a monitored pid and return the iterator pointing
587 /// to the previous modifiable value type. If there is no next
588 /// collection of statistics, this iterator will be set equal to
589 /// `end()`. The behavior of this function is undefined unless this
590 /// iterator is dereferenceable.
592
593 // ACCESSORS
594
595 /// Return a reference to the non-modifiable value type of this
596 /// iterator.
597 reference operator*() const;
598
599 /// Return a reference to the non-modifiable value type of this
600 /// iterator.
601 pointer operator->() const;
602
603 /// Return `true` if the specified `rhs` iterator points to the
604 /// same instance of the iterator's value type as "this" iterator,
605 /// and `false` otherwise. The behavior of this function is
606 /// undefined unless the `rhs` iterator and "this" iterator both
607 /// iterate over the same collection of Statistics.
608 bool operator==(const ConstIterator& rhs) const;
609
610 /// Return `true` if the specified `rhs` iterator does not point to
611 /// the same instance of the iterator's value type as "this"
612 /// iterator, and `false` otherwise. The behavior of this function
613 /// is undefined unless the `rhs` iterator and "this" iterator both
614 /// iterate over the same collection of Statistics.
615 bool operator!=(const ConstIterator& rhs) const;
616 };
617
618 // TRAITS
621
622 // CREATORS
623
624 /// Create an instance of this class to collect performance statistics
625 /// on demand (via the `collect` method). Optionally specify a
626 /// `basicAllocator` used to supply memory. If `basicAllocator` is 0,
627 /// the currently installed default allocator is used.
628 explicit
630
631 /// Create an instance of this class that uses the specified `scheduler`
632 /// to automatically collect performance statistics every specified
633 /// `interval` (specified in seconds). Optionally specify a
634 /// `basicAllocator` used to supply memory. If `basicAllocator` is 0,
635 /// the currently installed default allocator is used. A non-positive
636 /// `interval` value indicates that performance statistics should *not* be
637 /// automatically collected--in this case the user is responsible for
638 /// manually calling the `collect` function.
640 double interval,
641 bslma::Allocator *basicAllocator = 0);
642
643 /// Destroy this object.
645
646 // MANIPULATORS
647
648 /// Register the specified process `pid` having the specified user-defined
649 /// `description` with this performance monitor. After registration,
650 /// performance statistics will be collected for the `pid` upon invocation
651 /// of the `collect` function. A `pid` value of zero is translated to the
652 /// current process id. Return 0 on success or a non-zero value otherwise.
653 int registerPid(int pid, const bsl::string& description);
654
655 /// Unregister the specified process `pid` from the performance monitor.
656 /// After unregistration, to statistics for the `pid` will be no longer be
657 /// available unless the `pid` is re-registered with the performance
658 /// monitor through calling `registerPid`. A `pid` value of zero is
659 /// translated to the current process id. Return 0 on success or a
660 /// non-zero value otherwise.
661 int unregisterPid(int pid);
662
663 /// Set the specified time `interval`, in seconds, after which statistics
664 /// for each registered pid are automatically collected.
665 ///
666 /// \pre The behavior is undefined unless a scheduler was supplied at the construction of this
667 /// performance monitor. A non-positive `interval` value indicates that
668 /// performance statistics should not be automatically collected--in this
669 /// case the user is responsible for manually calling the `collect`
670 /// function.
671 void setCollectionInterval(double interval);
672
673 /// Collect performance statistics for each registered pid.
674 void collect();
675
676 /// Reset the collected min, max, and average values collected for each measure for each monitored process.
677 ///
678 /// \note Note that this method will call
679 /// `collect` once for each monitored process, so the statistics after this
680 /// method returns will be based on the values collected thereby.
682
683 // ACCESSORS
684
685 /// Return an iterator positioned at the first set of collected
686 /// performance statistics.
687 ConstIterator begin() const;
688
689 /// Return an iterator that represents the end of the sequence of sets
690 /// of collected performance statistics.
691 ConstIterator end() const;
692
693 /// Return the iterator pointing to the set of collected performance
694 /// statistics for the specified `pid` if `pid` has been registered with
695 /// this performance monitor through the `registerPid` function, otherwise
696 /// return `end()`. A `pid` value of zero is translated to the current
697 /// process id.
698 ConstIterator find(int pid) const;
699
700 /// Return the number of processes registered for statistics collection.
701 int numRegisteredPids() const;
702};
703
704#if defined(BSLS_PLATFORM_OS_LINUX) || defined(BSLS_PLATFORM_OS_CYGWIN)
705
706/// Describes the fields present in /proc/<pid>/stat. For a complete
707/// description of each field, see `man proc`.
708///
709///
710/// \note Note that sizes of the data fields are defined in terms of scanf(3)
711/// format specifiers, such as %d, %lu or %c. There is no good way to know
712/// if %lu is 32-bit wide or 64-bit, because the code can be built in the
713/// -m32 mode making sizeof(unsigned long)==4 and executed on a 64bit
714/// platform where the kernel thinks that %lu can represent 64-bit wide
715/// integers. Therefore we use `Uint64` regardless of the build
716/// configuration.
717///
718/// See @ref balb_performancemonitor
719struct PerformanceMonitor_LinuxProcStatistics {
720
721 // PUBLIC TYPES
722 typedef bsls::Types::Int64 LdType;
723 typedef bsls::Types::Uint64 LuType;
724 typedef bsls::Types::Uint64 LluType;
725
726 // PUBLIC DATA
727 int d_pid; // process pid
728 bsl::string d_comm; // filename of executable
729 char d_state; // process state
730 int d_ppid; // process's parent pid
731 int d_pgrp; // process group id
732 int d_session; // process session id
733 int d_tty_nr; // the tty used by the process
734 int d_tpgid; // tty owner's group id
735 unsigned int d_flags; // kernel flags
736 LuType d_minflt; // num minor page faults
737 LuType d_cminflt; // num minor page faults - children
738 LuType d_majflt; // num major page faults
739 LuType d_cmajflt; // num major page faults - children
740 LuType d_utime; // num jiffies in user mode
741 LuType d_stime; // num jiffies in kernel mode
742 LdType d_cutime; // num jiffies, user mode, children
743 LdType d_cstime; // num jiffies, kernel mode, children
744 LdType d_priority; // standard nice value, plus fifteen
745 LdType d_nice; // nice value
746 LdType d_numThreads; // number of threads (since Linux 2.6)
747 LdType d_itrealvalue; // num jiffies before next SIGALRM
748 LluType d_starttime; // time in jiffies since system boot
749 LuType d_vsize; // virtual memory size, in bytes
750 LdType d_rss; // resident set size, in pages
751
752 // Note that subsequent fields present in '/proc/<pid>/stat' are not
753 // required for any collected measures.
754
755 // CLASS METHOD
756
757 /// For the specified process id `pid`, load the contents of the file
758 /// `/proc/<pid>/stat` into the specified `buffer`. Return 0 on success
759 /// and a non-zero value otherwise.
760 static int readProcStatString(bsl::string *buffer, int pid);
761
762 private:
763 // NOT IMPLEMENTED
764
765 public:
766 // CREATORS
767
768 /// Default construct all fields in this object.
769 PerformanceMonitor_LinuxProcStatistics();
770
771 // PerformanceMonitor_LinuxProcStatistics(
772 // const PerformanceMonitor_LinuxProcStatistics&) = default;
773
774 // MANIPULATORS
775 // PerformanceMonitor_LinuxProcStatistics& operator=(
776 // const PerformanceMonitor_LinuxProcStatistics& rhs) = default;
777 // Copy all fields of the specified 'rhs' to this object, and return a
778 // reference to it.
779
780 /// Parse the specified `procStatString` and populate all the fields in
781 /// this `struct`. Check that the specified `pid` matches the `pid`
782 /// field in the string. Return 0 on success and a non-zero value
783 /// otherwise.
784 int parseProcStatString(const bsl::string& procStatString, int pid);
785};
786
787#endif
788
789// ============================================================================
790// INLINE DEFINITIONS
791// ============================================================================
792
793 // ---------------------------------------
794 // class PerformanceMonitor::ConstIterator
795 // ---------------------------------------
796
797// CREATORS
798inline
803
804inline
807 bslmt::RWMutex *mapGuard)
808: d_it(it)
809, d_mapGuard_p(mapGuard)
810{
811}
812
813// ACCESSORS
814inline
817{
818 bslmt::ReadLockGuard<bslmt::RWMutex> guard(d_mapGuard_p);
819 return *d_it->second.first;
820}
821
822inline
825{
826 bslmt::ReadLockGuard<bslmt::RWMutex> guard(d_mapGuard_p);
827 return d_it->second.first.get();
828}
829
830// MANIPULATORS
831inline
834{
835 bslmt::ReadLockGuard<bslmt::RWMutex> guard(d_mapGuard_p);
836 ++d_it;
837 return *this;
838}
839
840inline
843{
845 ++*this;
846 return temp;
847}
848
849// ACCESSORS
850inline
852 const ConstIterator& rhs) const
853{
854 return d_it == rhs.d_it;
855}
856
857inline
859 const ConstIterator& rhs) const
860{
861 return d_it != rhs.d_it;
862}
863
864 // ------------------------------------
865 // class PerformanceMonitor::Statistics
866 // ------------------------------------
867
868// ACCESSORS
869inline
871{
872 BSLS_ASSERT_SAFE(measure >= 0 && measure < e_NUM_MEASURES);
873
875 return d_lstData[measure];
876}
877
878inline
880{
881 BSLS_ASSERT_SAFE(measure >= 0 && measure < e_NUM_MEASURES);
882
884 return d_minData[measure];
885}
886
887inline
889{
890 BSLS_ASSERT_SAFE(measure >= 0 && measure < e_NUM_MEASURES);
891
893 return d_maxData[measure];
894}
895
896inline
898{
899 return d_pid;
900}
901
902inline
904{
905 return d_description;
906}
907
908inline
910{
912 return d_elapsedTime;
913}
914
915inline
917{
918 return d_startTimeUtc;
919}
920
921 // ------------------------
922 // class PerformanceMonitor
923 // ------------------------
924
925// ACCESSORS
926inline
929{
930 bslmt::ReadLockGuard<bslmt::RWMutex> guard(&d_mapGuard);
931 return ConstIterator(d_pidMap.begin(), &d_mapGuard);
932}
933
934inline
937{
938 bslmt::ReadLockGuard<bslmt::RWMutex> guard(&d_mapGuard);
939 return ConstIterator(d_pidMap.end(), &d_mapGuard);
940}
941
942inline
945{
946 if (0 == pid) {
948 }
949
950 bslmt::ReadLockGuard<bslmt::RWMutex> guard(&d_mapGuard);
951 return ConstIterator(d_pidMap.find(pid), &d_mapGuard);
952}
953
954inline
955int
957{
958 bslmt::ReadLockGuard<bslmt::RWMutex> guard(&d_mapGuard);
959 return static_cast<int>(d_pidMap.size());
960}
961
962} // close package namespace
963
964
965#endif
966
967// ----------------------------------------------------------------------------
968// Copyright 2018 Bloomberg Finance L.P.
969//
970// Licensed under the Apache License, Version 2.0 (the "License");
971// you may not use this file except in compliance with the License.
972// You may obtain a copy of the License at
973//
974// http://www.apache.org/licenses/LICENSE-2.0
975//
976// Unless required by applicable law or agreed to in writing, software
977// distributed under the License is distributed on an "AS IS" BASIS,
978// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
979// See the License for the specific language governing permissions and
980// limitations under the License.
981// ----------------------------- END-OF-FILE ----------------------------------
982
983/** @} */
984/** @} */
985/** @} */
Definition balb_performancemonitor.h:530
const Statistics & reference
Definition balb_performancemonitor.h:568
bsl::forward_iterator_tag iterator_category
Definition balb_performancemonitor.h:552
const Statistics * pointer
Definition balb_performancemonitor.h:564
bool operator!=(const ConstIterator &rhs) const
Definition balb_performancemonitor.h:858
reference operator*() const
Definition balb_performancemonitor.h:816
pointer operator->() const
Definition balb_performancemonitor.h:824
bool operator==(const ConstIterator &rhs) const
Definition balb_performancemonitor.h:851
ConstIterator()
Create an instance of this class having an invalid value.
Definition balb_performancemonitor.h:799
ConstIterator & operator++()
Definition balb_performancemonitor.h:833
Statistics value_type
Definition balb_performancemonitor.h:556
bsl::ptrdiff_t difference_type
Definition balb_performancemonitor.h:560
Definition balb_performancemonitor.h:406
Statistics(const Statistics &original, bslma::Allocator *basicAllocator=0)
Statistics(bslma::Allocator *basicAllocator=0)
double minValue(Measure measure) const
Definition balb_performancemonitor.h:879
const bsl::string & description() const
Definition balb_performancemonitor.h:903
void print(bsl::ostream &os) const
Print all collected statistics to the specified os stream.
double avgValue(Measure measure) const
void print(bsl::ostream &os, Measure measure) const
Print the specified measure to the specified os stream.
double maxValue(Measure measure) const
Definition balb_performancemonitor.h:888
double elapsedTime() const
Definition balb_performancemonitor.h:909
int pid() const
Return the pid for which these statistics were collected.
Definition balb_performancemonitor.h:897
double latestValue(Measure measure) const
Definition balb_performancemonitor.h:870
BSLMF_NESTED_TRAIT_DECLARATION(Statistics, bslma::UsesBslmaAllocator)
void print(bsl::ostream &os, const char *measureIdentifier) const
const bdlt::Datetime & startupTime() const
Return the startup time in Coordinated Universal Time.
Definition balb_performancemonitor.h:916
Definition balb_performancemonitor.h:251
int registerPid(int pid, const bsl::string &description)
ConstIterator end() const
Definition balb_performancemonitor.h:936
BSLMF_NESTED_TRAIT_DECLARATION(PerformanceMonitor, bslma::UsesBslmaAllocator)
~PerformanceMonitor()
Destroy this object.
PerformanceMonitor(bslma::Allocator *basicAllocator=0)
void collect()
Collect performance statistics for each registered pid.
ConstIterator find(int pid) const
Definition balb_performancemonitor.h:944
ConstIterator begin() const
Definition balb_performancemonitor.h:928
void setCollectionInterval(double interval)
int unregisterPid(int pid)
Measure
Definition balb_performancemonitor.h:263
@ e_CPU_UTIL_USER
Definition balb_performancemonitor.h:268
@ e_RESIDENT_SIZE
Definition balb_performancemonitor.h:270
@ e_CPU_UTIL
Definition balb_performancemonitor.h:267
@ e_CPU_TIME_SYSTEM
Definition balb_performancemonitor.h:266
@ e_NUM_MEASURES
Definition balb_performancemonitor.h:274
@ e_CPU_UTIL_SYSTEM
Definition balb_performancemonitor.h:269
@ e_CPU_TIME
Definition balb_performancemonitor.h:264
@ e_NUM_THREADS
Definition balb_performancemonitor.h:271
@ BSLA_DEPRECATED
Definition balb_performancemonitor.h:276
@ e_VIRTUAL_SIZE
Definition balb_performancemonitor.h:273
@ e_NUM_PAGEFAULTS
Definition balb_performancemonitor.h:272
@ e_CPU_TIME_USER
Definition balb_performancemonitor.h:265
PerformanceMonitor(bdlmt::TimerEventScheduler *scheduler, double interval, bslma::Allocator *basicAllocator=0)
int numRegisteredPids() const
Return the number of processes registered for statistics collection.
Definition balb_performancemonitor.h:956
Definition bdlmt_timereventscheduler.h:445
int Handle
Definition bdlmt_timereventscheduler.h:506
Definition bdlt_datetime.h:330
Definition bslstl_string.h:1252
Definition bslstl_map.h:653
BloombergLP::bslstl::TreeIterator< const value_type, Node, difference_type > const_iterator
Definition bslstl_map.h:758
iterator end() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_map.h:3308
iterator find(const key_type &key)
Definition bslstl_map.h:1885
size_type size() const BSLS_KEYWORD_NOEXCEPT
Return the number of elements in this map.
Definition bslstl_map.h:4039
iterator begin() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_map.h:3300
Definition bslstl_sharedptr.h:1838
Definition bslma_allocator.h:545
Definition bslmt_rwmutex.h:148
Definition bslmt_readlockguard.h:287
Definition bsls_timeinterval.h:307
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1917
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition balb_controlmanager.h:144
static int getProcessId()
Definition bslma_usesbslmaallocator.h:344
unsigned long long Uint64
Definition bsls_types.h:139
long long Int64
Definition bsls_types.h:134