/MagickCore/timer.c

https://gitlab.com/jiapei100/ImageMagick · C · 477 lines · 176 code · 6 blank · 295 comment · 37 complexity · 9eebc4c67ab671cfad97e59b0dbd0b02 MD5 · raw file

  1. /*
  2. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  3. % %
  4. % %
  5. % %
  6. % TTTTT IIIII M M EEEEE RRRR %
  7. % T I MM MM E R R %
  8. % T I M M M EEE RRRR %
  9. % T I M M E R R %
  10. % T IIIII M M EEEEE R R %
  11. % %
  12. % %
  13. % MagickCore Timing Methods %
  14. % %
  15. % Software Design %
  16. % Cristy %
  17. % January 1993 %
  18. % %
  19. % %
  20. % Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization %
  21. % dedicated to making software imaging solutions freely available. %
  22. % %
  23. % You may not use this file except in compliance with the License. You may %
  24. % obtain a copy of the License at %
  25. % %
  26. % http://www.imagemagick.org/script/license.php %
  27. % %
  28. % Unless required by applicable law or agreed to in writing, software %
  29. % distributed under the License is distributed on an "AS IS" BASIS, %
  30. % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
  31. % See the License for the specific language governing permissions and %
  32. % limitations under the License. %
  33. % %
  34. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  35. %
  36. % Contributed by Bill Radcliffe and Bob Friesenhahn.
  37. %
  38. */
  39. /*
  40. Include declarations.
  41. */
  42. #include "MagickCore/studio.h"
  43. #include "MagickCore/exception.h"
  44. #include "MagickCore/exception-private.h"
  45. #include "MagickCore/log.h"
  46. #include "MagickCore/memory_.h"
  47. #include "MagickCore/nt-base-private.h"
  48. #include "MagickCore/timer.h"
  49. /*
  50. Define declarations.
  51. */
  52. #if !defined(CLOCKS_PER_SEC)
  53. #define CLOCKS_PER_SEC 100
  54. #endif
  55. /*
  56. Forward declarations.
  57. */
  58. static double
  59. UserTime(void);
  60. static void
  61. StopTimer(TimerInfo *);
  62. /*
  63. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  64. % %
  65. % %
  66. % %
  67. % A c q u i r e T i m e r I n f o %
  68. % %
  69. % %
  70. % %
  71. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  72. %
  73. % AcquireTimerInfo() initializes the TimerInfo structure. It effectively
  74. % creates a stopwatch and starts it.
  75. %
  76. % The format of the AcquireTimerInfo method is:
  77. %
  78. % TimerInfo *AcquireTimerInfo(void)
  79. %
  80. */
  81. MagickExport TimerInfo *AcquireTimerInfo(void)
  82. {
  83. TimerInfo
  84. *timer_info;
  85. timer_info=(TimerInfo *) AcquireMagickMemory(sizeof(*timer_info));
  86. if (timer_info == (TimerInfo *) NULL)
  87. ThrowFatalException(ResourceLimitFatalError,"UnableToAcquireString");
  88. (void) ResetMagickMemory(timer_info,0,sizeof(*timer_info));
  89. timer_info->signature=MagickCoreSignature;
  90. GetTimerInfo(timer_info);
  91. return(timer_info);
  92. }
  93. /*
  94. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  95. % %
  96. % %
  97. % %
  98. % C o n t i n u e T i m e r %
  99. % %
  100. % %
  101. % %
  102. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  103. %
  104. % ContinueTimer() resumes a stopped stopwatch. The stopwatch continues
  105. % counting from the last StartTimer() onwards.
  106. %
  107. % The format of the ContinueTimer method is:
  108. %
  109. % MagickBooleanType ContinueTimer(TimerInfo *time_info)
  110. %
  111. % A description of each parameter follows.
  112. %
  113. % o time_info: Time statistics structure.
  114. %
  115. */
  116. MagickExport MagickBooleanType ContinueTimer(TimerInfo *time_info)
  117. {
  118. assert(time_info != (TimerInfo *) NULL);
  119. assert(time_info->signature == MagickCoreSignature);
  120. if (time_info->state == UndefinedTimerState)
  121. return(MagickFalse);
  122. if (time_info->state == StoppedTimerState)
  123. {
  124. time_info->user.total-=time_info->user.stop-time_info->user.start;
  125. time_info->elapsed.total-=time_info->elapsed.stop-
  126. time_info->elapsed.start;
  127. }
  128. time_info->state=RunningTimerState;
  129. return(MagickTrue);
  130. }
  131. /*
  132. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  133. % %
  134. % %
  135. % %
  136. % D e s t r o y T i m e r I n f o %
  137. % %
  138. % %
  139. % %
  140. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  141. %
  142. % DestroyTimerInfo() zeros memory associated with the TimerInfo structure.
  143. %
  144. % The format of the DestroyTimerInfo method is:
  145. %
  146. % TimerInfo *DestroyTimerInfo(TimerInfo *timer_info)
  147. %
  148. % A description of each parameter follows:
  149. %
  150. % o timer_info: The cipher context.
  151. %
  152. */
  153. MagickExport TimerInfo *DestroyTimerInfo(TimerInfo *timer_info)
  154. {
  155. assert(timer_info != (TimerInfo *) NULL);
  156. assert(timer_info->signature == MagickCoreSignature);
  157. timer_info->signature=(~MagickCoreSignature);
  158. timer_info=(TimerInfo *) RelinquishMagickMemory(timer_info);
  159. return(timer_info);
  160. }
  161. /*
  162. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  163. % %
  164. % %
  165. % %
  166. + E l a p s e d T i m e %
  167. % %
  168. % %
  169. % %
  170. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  171. %
  172. % ElapsedTime() returns the elapsed time (in seconds) since the last call to
  173. % StartTimer().
  174. %
  175. % The format of the ElapsedTime method is:
  176. %
  177. % double ElapsedTime()
  178. %
  179. */
  180. static double ElapsedTime(void)
  181. {
  182. #if defined(HAVE_CLOCK_GETTIME)
  183. #define NANOSECONDS_PER_SECOND 1000000000.0
  184. #if defined(CLOCK_HIGHRES)
  185. # define CLOCK_ID CLOCK_HIGHRES
  186. #elif defined(CLOCK_MONOTONIC_RAW)
  187. # define CLOCK_ID CLOCK_MONOTONIC_RAW
  188. #elif defined(CLOCK_MONOTONIC_PRECISE)
  189. # define CLOCK_ID CLOCK_MONOTONIC_PRECISE
  190. #elif defined(CLOCK_MONOTONIC)
  191. # define CLOCK_ID CLOCK_MONOTONIC
  192. #else
  193. # define CLOCK_ID CLOCK_REALTIME
  194. #endif
  195. struct timespec
  196. timer;
  197. (void) clock_gettime(CLOCK_ID,&timer);
  198. return((double) timer.tv_sec+timer.tv_nsec/NANOSECONDS_PER_SECOND);
  199. #elif defined(MAGICKCORE_HAVE_TIMES) && defined(MAGICKCORE_HAVE_SYSCONF)
  200. struct tms
  201. timer;
  202. return((double) times(&timer)/sysconf(_SC_CLK_TCK));
  203. #else
  204. #if defined(MAGICKCORE_WINDOWS_SUPPORT)
  205. return(NTElapsedTime());
  206. #else
  207. return((double) clock()/CLOCKS_PER_SEC);
  208. #endif
  209. #endif
  210. }
  211. /*
  212. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  213. % %
  214. % %
  215. % %
  216. % G e t E l a p s e d T i m e %
  217. % %
  218. % %
  219. % %
  220. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  221. %
  222. % GetElapsedTime() returns the elapsed time (in seconds) passed between the
  223. % start and stop events. If the stopwatch is still running, it is stopped
  224. % first.
  225. %
  226. % The format of the GetElapsedTime method is:
  227. %
  228. % double GetElapsedTime(TimerInfo *time_info)
  229. %
  230. % A description of each parameter follows.
  231. %
  232. % o time_info: Timer statistics structure.
  233. %
  234. */
  235. MagickExport double GetElapsedTime(TimerInfo *time_info)
  236. {
  237. assert(time_info != (TimerInfo *) NULL);
  238. assert(time_info->signature == MagickCoreSignature);
  239. if (time_info->state == UndefinedTimerState)
  240. return(0.0);
  241. if (time_info->state == RunningTimerState)
  242. StopTimer(time_info);
  243. return(time_info->elapsed.total);
  244. }
  245. /*
  246. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  247. % %
  248. % %
  249. % %
  250. + G e t T i m e r I n f o %
  251. % %
  252. % %
  253. % %
  254. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  255. %
  256. % GetTimerInfo() initializes the TimerInfo structure.
  257. %
  258. % The format of the GetTimerInfo method is:
  259. %
  260. % void GetTimerInfo(TimerInfo *time_info)
  261. %
  262. % A description of each parameter follows.
  263. %
  264. % o time_info: Timer statistics structure.
  265. %
  266. */
  267. MagickExport void GetTimerInfo(TimerInfo *time_info)
  268. {
  269. /*
  270. Create a stopwatch and start it.
  271. */
  272. assert(time_info != (TimerInfo *) NULL);
  273. (void) ResetMagickMemory(time_info,0,sizeof(*time_info));
  274. time_info->state=UndefinedTimerState;
  275. time_info->signature=MagickCoreSignature;
  276. StartTimer(time_info,MagickTrue);
  277. }
  278. /*
  279. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  280. % %
  281. % %
  282. % %
  283. % G e t U s e r T i m e %
  284. % %
  285. % %
  286. % %
  287. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  288. %
  289. % GetUserTime() returns the User time (user and system) by the operating
  290. % system (in seconds) between the start and stop events. If the stopwatch is
  291. % still running, it is stopped first.
  292. %
  293. % The format of the GetUserTime method is:
  294. %
  295. % double GetUserTime(TimerInfo *time_info)
  296. %
  297. % A description of each parameter follows.
  298. %
  299. % o time_info: Timer statistics structure.
  300. %
  301. */
  302. MagickExport double GetUserTime(TimerInfo *time_info)
  303. {
  304. assert(time_info != (TimerInfo *) NULL);
  305. assert(time_info->signature == MagickCoreSignature);
  306. if (time_info->state == UndefinedTimerState)
  307. return(0.0);
  308. if (time_info->state == RunningTimerState)
  309. StopTimer(time_info);
  310. return(time_info->user.total);
  311. }
  312. /*
  313. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  314. % %
  315. % %
  316. % %
  317. % R e s e t T i m e r %
  318. % %
  319. % %
  320. % %
  321. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  322. %
  323. % ResetTimer() resets the stopwatch.
  324. %
  325. % The format of the ResetTimer method is:
  326. %
  327. % void ResetTimer(TimerInfo *time_info)
  328. %
  329. % A description of each parameter follows.
  330. %
  331. % o time_info: Timer statistics structure.
  332. %
  333. */
  334. MagickExport void ResetTimer(TimerInfo *time_info)
  335. {
  336. assert(time_info != (TimerInfo *) NULL);
  337. assert(time_info->signature == MagickCoreSignature);
  338. StopTimer(time_info);
  339. time_info->elapsed.stop=0.0;
  340. time_info->user.stop=0.0;
  341. }
  342. /*
  343. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  344. % %
  345. % %
  346. % %
  347. + S t a r t T i m e r %
  348. % %
  349. % %
  350. % %
  351. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  352. %
  353. % StartTimer() starts the stopwatch.
  354. %
  355. % The format of the StartTimer method is:
  356. %
  357. % void StartTimer(TimerInfo *time_info,const MagickBooleanType reset)
  358. %
  359. % A description of each parameter follows.
  360. %
  361. % o time_info: Timer statistics structure.
  362. %
  363. % o reset: If reset is MagickTrue, then the stopwatch is reset prior to
  364. % starting. If reset is MagickFalse, then timing is continued without
  365. % resetting the stopwatch.
  366. %
  367. */
  368. MagickExport void StartTimer(TimerInfo *time_info,const MagickBooleanType reset)
  369. {
  370. assert(time_info != (TimerInfo *) NULL);
  371. assert(time_info->signature == MagickCoreSignature);
  372. if (reset != MagickFalse)
  373. {
  374. /*
  375. Reset the stopwatch before starting it.
  376. */
  377. time_info->user.total=0.0;
  378. time_info->elapsed.total=0.0;
  379. }
  380. if (time_info->state != RunningTimerState)
  381. {
  382. time_info->elapsed.start=ElapsedTime();
  383. time_info->user.start=UserTime();
  384. }
  385. time_info->state=RunningTimerState;
  386. }
  387. /*
  388. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  389. % %
  390. % %
  391. % %
  392. + S t o p T i m e r %
  393. % %
  394. % %
  395. % %
  396. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  397. %
  398. % StopTimer() stops the stopwatch.
  399. %
  400. % The format of the StopTimer method is:
  401. %
  402. % void StopTimer(TimerInfo *time_info)
  403. %
  404. % A description of each parameter follows.
  405. %
  406. % o time_info: Timer statistics structure.
  407. %
  408. */
  409. static void StopTimer(TimerInfo *time_info)
  410. {
  411. assert(time_info != (TimerInfo *) NULL);
  412. assert(time_info->signature == MagickCoreSignature);
  413. time_info->elapsed.stop=ElapsedTime();
  414. time_info->user.stop=UserTime();
  415. if (time_info->state == RunningTimerState)
  416. {
  417. time_info->user.total+=time_info->user.stop-
  418. time_info->user.start+MagickEpsilon;
  419. time_info->elapsed.total+=time_info->elapsed.stop-
  420. time_info->elapsed.start+MagickEpsilon;
  421. }
  422. time_info->state=StoppedTimerState;
  423. }
  424. /*
  425. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  426. % %
  427. % %
  428. % %
  429. + U s e r T i m e %
  430. % %
  431. % %
  432. % %
  433. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  434. %
  435. % UserTime() returns the total time the process has been scheduled (in
  436. % seconds) since the last call to StartTimer().
  437. %
  438. % The format of the UserTime method is:
  439. %
  440. % double UserTime()
  441. %
  442. */
  443. static double UserTime(void)
  444. {
  445. #if defined(MAGICKCORE_HAVE_TIMES) && defined(MAGICKCORE_HAVE_SYSCONF)
  446. struct tms
  447. timer;
  448. (void) times(&timer);
  449. return((double) (timer.tms_utime+timer.tms_stime)/sysconf(_SC_CLK_TCK));
  450. #else
  451. #if defined(MAGICKCORE_WINDOWS_SUPPORT)
  452. return(NTUserTime());
  453. #else
  454. return((double) clock()/CLOCKS_PER_SEC);
  455. #endif
  456. #endif
  457. }