You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

369 lines
13 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: unixstl/performance/processtimes_counter.hpp
  3. *
  4. * Purpose: UNIXSTL process-time performance counter class.
  5. *
  6. * Created: 9th June 2006
  7. * Updated: 10th August 2009
  8. *
  9. * Home: http://stlsoft.org/
  10. *
  11. * Copyright (c) 2006-2009, Matthew Wilson and Synesis Software
  12. * All rights reserved.
  13. *
  14. * Redistribution and use in source and binary forms, with or without
  15. * modification, are permitted provided that the following conditions are met:
  16. *
  17. * - Redistributions of source code must retain the above copyright notice, this
  18. * list of conditions and the following disclaimer.
  19. * - Redistributions in binary form must reproduce the above copyright notice,
  20. * this list of conditions and the following disclaimer in the documentation
  21. * and/or other materials provided with the distribution.
  22. * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
  23. * any contributors may be used to endorse or promote products derived from
  24. * this software without specific prior written permission.
  25. *
  26. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  27. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  30. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  31. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  32. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  33. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  34. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  35. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  36. * POSSIBILITY OF SUCH DAMAGE.
  37. *
  38. * ////////////////////////////////////////////////////////////////////// */
  39. /** \file unixstl/performance/processtimes_counter.hpp
  40. *
  41. * \brief [C++ only] Definition of the
  42. * \link unixstl::processtimes_counter processtimes_counter\endlink class
  43. * (\ref group__library__performance "Performance" Library).
  44. */
  45. #ifndef WINSTL_INCL_UNIXSTL_PERFORMANCE_HPP_PROCESSTIMES_COUNTER
  46. #define UNIXSTL_INCL_UNIXSTL_PERFORMANCE_HPP_PROCESSTIMES_COUNTER
  47. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  48. # define UNIXSTL_VER_UNIXSTL_PERFORMANCE_HPP_PROCESSTIMES_COUNTER_MAJOR 1
  49. # define UNIXSTL_VER_UNIXSTL_PERFORMANCE_HPP_PROCESSTIMES_COUNTER_MINOR 0
  50. # define UNIXSTL_VER_UNIXSTL_PERFORMANCE_HPP_PROCESSTIMES_COUNTER_REVISION 7
  51. # define UNIXSTL_VER_UNIXSTL_PERFORMANCE_HPP_PROCESSTIMES_COUNTER_EDIT 13
  52. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  53. /* /////////////////////////////////////////////////////////////////////////
  54. * Includes
  55. */
  56. #ifndef UNIXSTL_INCL_UNIXSTL_H_UNIXSTL
  57. # include <unixstl/unixstl.h>
  58. #endif /* !UNIXSTL_INCL_UNIXSTL_H_UNIXSTL */
  59. #ifndef STLSOFT_INCL_SYS_H_TIME
  60. # define STLSOFT_INCL_SYS_H_TIME
  61. # include <sys/time.h>
  62. #endif /* !STLSOFT_INCL_SYS_H_TIME */
  63. #ifndef STLSOFT_INCL_SYS_H_RESOURCE
  64. # define STLSOFT_INCL_SYS_H_RESOURCE
  65. # include <sys/resource.h>
  66. #endif /* !STLSOFT_INCL_SYS_H_RESOURCE */
  67. /* /////////////////////////////////////////////////////////////////////////
  68. * Namespace
  69. */
  70. #ifndef _UNIXSTL_NO_NAMESPACE
  71. # if defined(_STLSOFT_NO_NAMESPACE) || \
  72. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  73. /* There is no stlsoft namespace, so must define ::unixstl */
  74. namespace unixstl
  75. {
  76. # else
  77. /* Define stlsoft::unixstl_project */
  78. namespace stlsoft
  79. {
  80. namespace unixstl_project
  81. {
  82. # endif /* _STLSOFT_NO_NAMESPACE */
  83. #endif /* !_UNIXSTL_NO_NAMESPACE */
  84. /* /////////////////////////////////////////////////////////////////////////
  85. * Classes
  86. */
  87. // class processtimes_counter
  88. /** \brief A performance counter that provides process-specific performance timings
  89. *
  90. * \ingroup group__library__performance
  91. *
  92. * This class uses the operating system's performance monitoring facilities to provide timing
  93. * information pertaining to the calling process only, irrespective of the activities of other
  94. * processes on the system. This class does not provide meaningful timing information on operating
  95. * systems that do not provide process-specific monitoring.
  96. */
  97. class processtimes_counter
  98. {
  99. public:
  100. typedef processtimes_counter class_type;
  101. typedef us_sint64_t epoch_type;
  102. public:
  103. /// \brief The interval type
  104. ///
  105. /// The type of the interval measurement, a 64-bit signed integer
  106. typedef us_sint64_t interval_type;
  107. // Construction
  108. public:
  109. processtimes_counter();
  110. // Operations
  111. public:
  112. /// \brief Starts measurement
  113. ///
  114. /// Begins the measurement period
  115. void start();
  116. /// \brief Ends measurement
  117. ///
  118. /// Ends the measurement period
  119. void stop();
  120. // Attributes
  121. public:
  122. // Kernel
  123. /// \brief The elapsed count in the measurement period for kernel mode activity
  124. ///
  125. /// This represents the extent, in machine-specific increments, of the measurement period for kernel mode activity
  126. interval_type get_kernel_period_count() const;
  127. /// \brief The number of whole seconds in the measurement period for kernel mode activity
  128. ///
  129. /// This represents the extent, in whole seconds, of the measurement period for kernel mode activity
  130. interval_type get_kernel_seconds() const;
  131. /// \brief The number of whole milliseconds in the measurement period for kernel mode activity
  132. ///
  133. /// This represents the extent, in whole milliseconds, of the measurement period for kernel mode activity
  134. interval_type get_kernel_milliseconds() const;
  135. /// \brief The number of whole microseconds in the measurement period for kernel mode activity
  136. ///
  137. /// This represents the extent, in whole microseconds, of the measurement period for kernel mode activity
  138. interval_type get_kernel_microseconds() const;
  139. // User
  140. /// \brief The elapsed count in the measurement period for user mode activity
  141. ///
  142. /// This represents the extent, in machine-specific increments, of the measurement period for user mode activity
  143. interval_type get_user_period_count() const;
  144. /// \brief The number of whole seconds in the measurement period for user mode activity
  145. ///
  146. /// This represents the extent, in whole seconds, of the measurement period for user mode activity
  147. interval_type get_user_seconds() const;
  148. /// \brief The number of whole milliseconds in the measurement period for user mode activity
  149. ///
  150. /// This represents the extent, in whole milliseconds, of the measurement period for user mode activity
  151. interval_type get_user_milliseconds() const;
  152. /// \brief The number of whole microseconds in the measurement period for user mode activity
  153. ///
  154. /// This represents the extent, in whole microseconds, of the measurement period for user mode activity
  155. interval_type get_user_microseconds() const;
  156. // Total
  157. /// \brief The elapsed count in the measurement period
  158. ///
  159. /// This represents the extent, in machine-specific increments, of the measurement period
  160. interval_type get_period_count() const;
  161. /// \brief The number of whole seconds in the measurement period
  162. ///
  163. /// This represents the extent, in whole seconds, of the measurement period
  164. interval_type get_seconds() const;
  165. /// \brief The number of whole milliseconds in the measurement period
  166. ///
  167. /// This represents the extent, in whole milliseconds, of the measurement period
  168. interval_type get_milliseconds() const;
  169. /// \brief The number of whole microseconds in the measurement period
  170. ///
  171. /// This represents the extent, in whole microseconds, of the measurement period
  172. interval_type get_microseconds() const;
  173. // Members
  174. private:
  175. typedef struct timeval timeval_t;
  176. timeval_t m_kernelStart;
  177. timeval_t m_kernelEnd;
  178. timeval_t m_userStart;
  179. timeval_t m_userEnd;
  180. };
  181. ////////////////////////////////////////////////////////////////////////////
  182. // Unit-testing
  183. #ifdef STLSOFT_UNITTEST
  184. # include "./unittest/processtimes_counter_unittest_.h"
  185. #endif /* STLSOFT_UNITTEST */
  186. /* ////////////////////////////////////////////////////////////////////// */
  187. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  188. inline processtimes_counter::processtimes_counter()
  189. {
  190. // Note that the constructor does nothing, for performance reasons. Calling
  191. // any of the Attribute methods before having gone through a start()-stop()
  192. // cycle will yield undefined results.
  193. }
  194. // Operations
  195. inline void processtimes_counter::start()
  196. {
  197. struct rusage r_usage;
  198. ::getrusage(RUSAGE_SELF, &r_usage);
  199. m_kernelStart = r_usage.ru_stime;
  200. m_userStart = r_usage.ru_utime;
  201. }
  202. inline void processtimes_counter::stop()
  203. {
  204. struct rusage r_usage;
  205. ::getrusage(RUSAGE_SELF, &r_usage);
  206. m_kernelEnd = r_usage.ru_stime;
  207. m_userEnd = r_usage.ru_utime;
  208. }
  209. // Kernel
  210. inline processtimes_counter::interval_type processtimes_counter::get_kernel_period_count() const
  211. {
  212. return get_kernel_microseconds();
  213. }
  214. inline processtimes_counter::interval_type processtimes_counter::get_kernel_seconds() const
  215. {
  216. UNIXSTL_MESSAGE_ASSERT("end before start: stop() must be called after start()", m_kernelStart.tv_sec <= m_kernelEnd.tv_sec);
  217. long secs = m_kernelEnd.tv_sec - m_kernelStart.tv_sec;
  218. long usecs = m_kernelEnd.tv_usec - m_kernelStart.tv_usec;
  219. UNIXSTL_ASSERT(usecs >= 0 || secs > 0);
  220. return secs + usecs / (1000 * 1000);
  221. }
  222. inline processtimes_counter::interval_type processtimes_counter::get_kernel_milliseconds() const
  223. {
  224. UNIXSTL_MESSAGE_ASSERT("end before start: stop() must be called after start()", m_kernelStart.tv_sec <= m_kernelEnd.tv_sec);
  225. long secs = m_kernelEnd.tv_sec - m_kernelStart.tv_sec;
  226. long usecs = m_kernelEnd.tv_usec - m_kernelStart.tv_usec;
  227. UNIXSTL_ASSERT(usecs >= 0 || secs > 0);
  228. return secs * 1000 + usecs / 1000;
  229. }
  230. inline processtimes_counter::interval_type processtimes_counter::get_kernel_microseconds() const
  231. {
  232. UNIXSTL_MESSAGE_ASSERT("end before start: stop() must be called after start()", m_kernelStart.tv_sec <= m_kernelEnd.tv_sec);
  233. long secs = m_kernelEnd.tv_sec - m_kernelStart.tv_sec;
  234. long usecs = m_kernelEnd.tv_usec - m_kernelStart.tv_usec;
  235. UNIXSTL_ASSERT(usecs >= 0 || secs > 0);
  236. return secs * (1000 * 1000) + usecs;
  237. }
  238. // User
  239. inline processtimes_counter::interval_type processtimes_counter::get_user_period_count() const
  240. {
  241. return get_user_microseconds();
  242. }
  243. inline processtimes_counter::interval_type processtimes_counter::get_user_seconds() const
  244. {
  245. UNIXSTL_MESSAGE_ASSERT("end before start: stop() must be called after start()", m_userStart.tv_sec <= m_userEnd.tv_sec);
  246. long secs = m_userEnd.tv_sec - m_userStart.tv_sec;
  247. long usecs = m_userEnd.tv_usec - m_userStart.tv_usec;
  248. UNIXSTL_ASSERT(usecs >= 0 || secs > 0);
  249. return secs + usecs / (1000 * 1000);
  250. }
  251. inline processtimes_counter::interval_type processtimes_counter::get_user_milliseconds() const
  252. {
  253. UNIXSTL_MESSAGE_ASSERT("end before start: stop() must be called after start()", m_userStart.tv_sec <= m_userEnd.tv_sec);
  254. long secs = m_userEnd.tv_sec - m_userStart.tv_sec;
  255. long usecs = m_userEnd.tv_usec - m_userStart.tv_usec;
  256. UNIXSTL_ASSERT(usecs >= 0 || secs > 0);
  257. return secs * 1000 + usecs / 1000;
  258. }
  259. inline processtimes_counter::interval_type processtimes_counter::get_user_microseconds() const
  260. {
  261. UNIXSTL_MESSAGE_ASSERT("end before start: stop() must be called after start()", m_userStart.tv_sec <= m_userEnd.tv_sec);
  262. long secs = m_userEnd.tv_sec - m_userStart.tv_sec;
  263. long usecs = m_userEnd.tv_usec - m_userStart.tv_usec;
  264. UNIXSTL_ASSERT(usecs >= 0 || secs > 0);
  265. return secs * (1000 * 1000) + usecs;
  266. }
  267. // Total
  268. inline processtimes_counter::interval_type processtimes_counter::get_period_count() const
  269. {
  270. return get_kernel_period_count() + get_user_period_count();
  271. }
  272. inline processtimes_counter::interval_type processtimes_counter::get_seconds() const
  273. {
  274. return get_period_count() / interval_type(10000000);
  275. }
  276. inline processtimes_counter::interval_type processtimes_counter::get_milliseconds() const
  277. {
  278. return get_period_count() / interval_type(10000);
  279. }
  280. inline processtimes_counter::interval_type processtimes_counter::get_microseconds() const
  281. {
  282. return get_period_count() / interval_type(10);
  283. }
  284. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  285. /* ////////////////////////////////////////////////////////////////////// */
  286. #ifndef _UNIXSTL_NO_NAMESPACE
  287. # if defined(_STLSOFT_NO_NAMESPACE) || \
  288. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  289. } // namespace unixstl
  290. # else
  291. } // namespace unixstl_project
  292. } // namespace stlsoft
  293. # endif /* _STLSOFT_NO_NAMESPACE */
  294. #endif /* !_UNIXSTL_NO_NAMESPACE */
  295. /* ////////////////////////////////////////////////////////////////////// */
  296. #endif /* !UNIXSTL_INCL_UNIXSTL_PERFORMANCE_HPP_PROCESSTIMES_COUNTER */
  297. /* ///////////////////////////// end of file //////////////////////////// */