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.

367 lines
12 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: winstl/performance/threadtimes_counter.hpp
  3. *
  4. * Purpose: WinSTL thread-time performance counter class.
  5. *
  6. * Created: 22nd March 2002
  7. * Updated: 6th May 2010
  8. *
  9. * Home: http://stlsoft.org/
  10. *
  11. * Copyright (c) 2002-2010, 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 winstl/performance/threadtimes_counter.hpp
  40. *
  41. * \brief [C++ only] Definition of the
  42. * \link winstl::threadtimes_counter threadtimes_counter\endlink class
  43. * (\ref group__library__performance "Performance" Library).
  44. */
  45. #ifndef WINSTL_INCL_WINSTL_PERFORMANCE_HPP_THREADTIMES_COUNTER
  46. #define WINSTL_INCL_WINSTL_PERFORMANCE_HPP_THREADTIMES_COUNTER
  47. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  48. # define WINSTL_VER_WINSTL_PERFORMANCE_HPP_THREADTIMES_COUNTER_MAJOR 4
  49. # define WINSTL_VER_WINSTL_PERFORMANCE_HPP_THREADTIMES_COUNTER_MINOR 0
  50. # define WINSTL_VER_WINSTL_PERFORMANCE_HPP_THREADTIMES_COUNTER_REVISION 3
  51. # define WINSTL_VER_WINSTL_PERFORMANCE_HPP_THREADTIMES_COUNTER_EDIT 48
  52. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  53. /* /////////////////////////////////////////////////////////////////////////
  54. * Includes
  55. */
  56. #ifndef WINSTL_INCL_WINSTL_H_WINSTL
  57. # include <winstl/winstl.h>
  58. #endif /* !WINSTL_INCL_WINSTL_H_WINSTL */
  59. /* /////////////////////////////////////////////////////////////////////////
  60. * Namespace
  61. */
  62. #ifndef _WINSTL_NO_NAMESPACE
  63. # if defined(_STLSOFT_NO_NAMESPACE) || \
  64. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  65. /* There is no stlsoft namespace, so must define ::winstl */
  66. namespace winstl
  67. {
  68. # else
  69. /* Define stlsoft::winstl_project */
  70. namespace stlsoft
  71. {
  72. namespace winstl_project
  73. {
  74. # endif /* _STLSOFT_NO_NAMESPACE */
  75. #endif /* !_WINSTL_NO_NAMESPACE */
  76. /* /////////////////////////////////////////////////////////////////////////
  77. * Classes
  78. */
  79. // class threadtimes_counter
  80. /** \brief A performance counter that provides thread-specific performance timings
  81. *
  82. * \ingroup group__library__performance
  83. *
  84. * This class uses the operating system's performance monitoring facilities to provide timing
  85. * information pertaining to the calling thread only, irrespective of the activities of other
  86. * threads on the system. This class does not provide meaningful timing information on operating
  87. * systems that do not provide thread-specific monitoring.
  88. */
  89. class threadtimes_counter
  90. {
  91. public:
  92. /// This type
  93. typedef threadtimes_counter class_type;
  94. private:
  95. typedef ws_sint64_t epoch_type;
  96. public:
  97. /// \brief The interval type
  98. ///
  99. /// The type of the interval measurement, a 64-bit signed integer
  100. typedef ws_sint64_t interval_type;
  101. // Construction
  102. public:
  103. /// \brief Constructor
  104. ///
  105. /// Creates an instance of the class, and caches the thread token so that measurements will
  106. /// be taken with respect to the thread in which the class was created.
  107. threadtimes_counter();
  108. // Operations
  109. public:
  110. /// \brief Starts measurement
  111. ///
  112. /// Begins the measurement period
  113. void start();
  114. /// \brief Ends measurement
  115. ///
  116. /// Ends the measurement period
  117. void stop();
  118. // Attributes
  119. public:
  120. // Kernel
  121. /// \brief The elapsed count in the measurement period for kernel mode activity
  122. ///
  123. /// This represents the extent, in machine-specific increments, of the measurement period for kernel mode activity
  124. interval_type get_kernel_period_count() const;
  125. /// \brief The number of whole seconds in the measurement period for kernel mode activity
  126. ///
  127. /// This represents the extent, in whole seconds, of the measurement period for kernel mode activity
  128. interval_type get_kernel_seconds() const;
  129. /// \brief The number of whole milliseconds in the measurement period for kernel mode activity
  130. ///
  131. /// This represents the extent, in whole milliseconds, of the measurement period for kernel mode activity
  132. interval_type get_kernel_milliseconds() const;
  133. /// \brief The number of whole microseconds in the measurement period for kernel mode activity
  134. ///
  135. /// This represents the extent, in whole microseconds, of the measurement period for kernel mode activity
  136. interval_type get_kernel_microseconds() const;
  137. // User
  138. /// \brief The elapsed count in the measurement period for user mode activity
  139. ///
  140. /// This represents the extent, in machine-specific increments, of the measurement period for user mode activity
  141. interval_type get_user_period_count() const;
  142. /// \brief The number of whole seconds in the measurement period for user mode activity
  143. ///
  144. /// This represents the extent, in whole seconds, of the measurement period for user mode activity
  145. interval_type get_user_seconds() const;
  146. /// \brief The number of whole milliseconds in the measurement period for user mode activity
  147. ///
  148. /// This represents the extent, in whole milliseconds, of the measurement period for user mode activity
  149. interval_type get_user_milliseconds() const;
  150. /// \brief The number of whole microseconds in the measurement period for user mode activity
  151. ///
  152. /// This represents the extent, in whole microseconds, of the measurement period for user mode activity
  153. interval_type get_user_microseconds() const;
  154. // Total
  155. /// \brief The elapsed count in the measurement period
  156. ///
  157. /// This represents the extent, in machine-specific increments, of the measurement period
  158. interval_type get_period_count() const;
  159. /// \brief The number of whole seconds in the measurement period
  160. ///
  161. /// This represents the extent, in whole seconds, of the measurement period
  162. interval_type get_seconds() const;
  163. /// \brief The number of whole milliseconds in the measurement period
  164. ///
  165. /// This represents the extent, in whole milliseconds, of the measurement period
  166. interval_type get_milliseconds() const;
  167. /// \brief The number of whole microseconds in the measurement period
  168. ///
  169. /// This represents the extent, in whole microseconds, of the measurement period
  170. interval_type get_microseconds() const;
  171. private: // Implementation
  172. static epoch_type convert_(FILETIME const& ft);
  173. // Members
  174. private:
  175. epoch_type m_kernelStart;
  176. epoch_type m_kernelEnd;
  177. epoch_type m_userStart;
  178. epoch_type m_userEnd;
  179. HANDLE m_thread;
  180. };
  181. ////////////////////////////////////////////////////////////////////////////
  182. // Unit-testing
  183. #ifdef STLSOFT_UNITTEST
  184. # include "./unittest/threadtimes_counter_unittest_.h"
  185. #endif /* STLSOFT_UNITTEST */
  186. ////////////////////////////////////////////////////////////////////////////
  187. // Implementation
  188. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  189. inline /* static */ threadtimes_counter::epoch_type threadtimes_counter::convert_(FILETIME const& ft)
  190. {
  191. epoch_type r = ft.dwHighDateTime;
  192. r <<= 32;
  193. r += ft.dwLowDateTime;
  194. return r;
  195. }
  196. inline threadtimes_counter::threadtimes_counter()
  197. : m_thread(::GetCurrentThread())
  198. {
  199. // Note that the constructor does nothing, for performance reasons. Calling
  200. // any of the Attribute methods before having gone through a start()-stop()
  201. // cycle will yield undefined results.
  202. }
  203. // Operations
  204. inline void threadtimes_counter::start()
  205. {
  206. FILETIME creationTime;
  207. FILETIME exitTime;
  208. FILETIME kernelTime;
  209. FILETIME userTime;
  210. if(!::GetThreadTimes(m_thread, &creationTime, &exitTime, &kernelTime, &userTime))
  211. {
  212. m_kernelStart = 0;
  213. m_userStart = 0;
  214. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  215. ; // TODO: throw
  216. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  217. }
  218. else
  219. {
  220. m_kernelStart = convert_(kernelTime);
  221. m_userStart = convert_(userTime);
  222. }
  223. }
  224. inline void threadtimes_counter::stop()
  225. {
  226. FILETIME creationTime;
  227. FILETIME exitTime;
  228. FILETIME kernelTime;
  229. FILETIME userTime;
  230. if(!::GetThreadTimes(m_thread, &creationTime, &exitTime, &kernelTime, &userTime))
  231. {
  232. m_kernelEnd = 0;
  233. m_userEnd = 0;
  234. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  235. ; // TODO: throw
  236. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  237. }
  238. else
  239. {
  240. m_kernelEnd = convert_(kernelTime);
  241. m_userEnd = convert_(userTime);
  242. }
  243. }
  244. // Attributes
  245. // Kernel
  246. inline threadtimes_counter::interval_type threadtimes_counter::get_kernel_period_count() const
  247. {
  248. return static_cast<interval_type>(m_kernelEnd - m_kernelStart);
  249. }
  250. inline threadtimes_counter::interval_type threadtimes_counter::get_kernel_seconds() const
  251. {
  252. return get_kernel_period_count() / interval_type(10000000);
  253. }
  254. inline threadtimes_counter::interval_type threadtimes_counter::get_kernel_milliseconds() const
  255. {
  256. return get_kernel_period_count() / interval_type(10000);
  257. }
  258. inline threadtimes_counter::interval_type threadtimes_counter::get_kernel_microseconds() const
  259. {
  260. return get_kernel_period_count() / interval_type(10);
  261. }
  262. // User
  263. inline threadtimes_counter::interval_type threadtimes_counter::get_user_period_count() const
  264. {
  265. return static_cast<interval_type>(m_userEnd - m_userStart);
  266. }
  267. inline threadtimes_counter::interval_type threadtimes_counter::get_user_seconds() const
  268. {
  269. return get_user_period_count() / interval_type(10000000);
  270. }
  271. inline threadtimes_counter::interval_type threadtimes_counter::get_user_milliseconds() const
  272. {
  273. return get_user_period_count() / interval_type(10000);
  274. }
  275. inline threadtimes_counter::interval_type threadtimes_counter::get_user_microseconds() const
  276. {
  277. return get_user_period_count() / interval_type(10);
  278. }
  279. // Total
  280. inline threadtimes_counter::interval_type threadtimes_counter::get_period_count() const
  281. {
  282. return get_kernel_period_count() + get_user_period_count();
  283. }
  284. inline threadtimes_counter::interval_type threadtimes_counter::get_seconds() const
  285. {
  286. return get_period_count() / interval_type(10000000);
  287. }
  288. inline threadtimes_counter::interval_type threadtimes_counter::get_milliseconds() const
  289. {
  290. return get_period_count() / interval_type(10000);
  291. }
  292. inline threadtimes_counter::interval_type threadtimes_counter::get_microseconds() const
  293. {
  294. return get_period_count() / interval_type(10);
  295. }
  296. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  297. /* ////////////////////////////////////////////////////////////////////// */
  298. #ifndef _WINSTL_NO_NAMESPACE
  299. # if defined(_STLSOFT_NO_NAMESPACE) || \
  300. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  301. } // namespace winstl
  302. # else
  303. } // namespace winstl_project
  304. } // namespace stlsoft
  305. # endif /* _STLSOFT_NO_NAMESPACE */
  306. #endif /* !_WINSTL_NO_NAMESPACE */
  307. /* ////////////////////////////////////////////////////////////////////// */
  308. #endif /* !WINSTL_INCL_WINSTL_PERFORMANCE_HPP_THREADTIMES_COUNTER */
  309. /* ///////////////////////////// end of file //////////////////////////// */