1 // =================================================================================================
2 // Copyright 2006 Adobe Systems Incorporated
3 // All Rights Reserved.
4 //
5 // NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the terms
6 // of the Adobe license agreement accompanying it.
7 // =================================================================================================
8 
9 #include "public/include/XMP_Environment.h"
10 #include "public/include/XMP_Const.h"
11 
12 #include "source/PerfUtils.hpp"
13 
14 #include <stdio.h>
15 
16 #if XMP_WinBuild
17 	#pragma warning ( disable : 4996 )	// '...' was declared deprecated
18 #endif
19 
20 // =================================================================================================
21 // =================================================================================================
22 
23 #if XMP_WinBuild
24 
25 #pragma warning ( disable : 4800 )	// forcing bool to 0/1
26 
GetTimerInfo()27 const char * PerfUtils::GetTimerInfo()
28 {
29 	LARGE_INTEGER freq;
30 	static char msgBuffer[1000];
31 
32 	bool ok = (bool) QueryPerformanceFrequency ( &freq );
33 	if ( ! ok ) throw XMP_Error ( kXMPErr_ExternalFailure, "Failure from QueryPerformanceFrequency" );
34 
35 	if ( freq.HighPart != 0 ) {
36 		return "Windows PerfUtils measures finer than nanoseconds, using the QueryPerformanceCounter() timer";
37 	}
38 
39 	double rate = 1.0 / (double)freq.LowPart;
40 	_snprintf ( msgBuffer, sizeof(msgBuffer),
41 			   "Windows PerfUtils measures %e second, using the QueryPerformanceCounter() timer", rate );
42 	return msgBuffer;
43 
44 }	// PerfUtils::GetTimerInfo
45 
46 // ------------------------------------------------------------------------------------------------
47 
NoteThisMoment()48 PerfUtils::MomentValue PerfUtils::NoteThisMoment()
49 {
50 	LARGE_INTEGER now;
51 
52 	bool ok = (bool) QueryPerformanceCounter ( &now );
53 	if ( ! ok ) throw XMP_Error ( kXMPErr_ExternalFailure, "Failure from QueryPerformanceCounter" );
54 	return now.QuadPart;
55 
56 }	// PerfUtils::NoteThisMoment
57 
58 // ------------------------------------------------------------------------------------------------
59 
GetElapsedSeconds(PerfUtils::MomentValue start,PerfUtils::MomentValue finish)60 double PerfUtils::GetElapsedSeconds ( PerfUtils::MomentValue start, PerfUtils::MomentValue finish )
61 {
62 	LARGE_INTEGER freq;
63 
64 	bool ok = (bool) QueryPerformanceFrequency ( &freq );
65 	if ( ! ok ) throw XMP_Error ( kXMPErr_ExternalFailure, "Failure from QueryPerformanceFrequency" );
66 
67 	const double scale = (double)freq.QuadPart;
68 
69 	const double elapsed = (double)(finish - start) / scale;
70 	return elapsed;
71 
72 }	// PerfUtils::GetElapsedSeconds
73 
74 #endif
75 
76 // =================================================================================================
77 
78 #if XMP_UNIXBuild
79 
GetTimerInfo()80 const char * PerfUtils::GetTimerInfo()
81 {
82 	return "UNIX PerfUtils measures nano seconds, using the POSIX clock_gettime() timer";
83 }	// PerfUtils::GetTimerInfo
84 
85 // ------------------------------------------------------------------------------------------------
86 
NoteThisMoment()87 PerfUtils::MomentValue PerfUtils::NoteThisMoment()
88 {
89 	MomentValue moment = kZeroMoment;
90 	if ( clock_gettime( CLOCK_MONOTONIC, &moment ) != 0 )
91 		throw XMP_Error( kXMPErr_ExternalFailure, "Failure from clock_gettime" );
92 	return moment;
93 }	// PerfUtils::NoteThisMoment
94 
95 // ------------------------------------------------------------------------------------------------
96 
GetElapsedSeconds(PerfUtils::MomentValue start,PerfUtils::MomentValue finish)97 double PerfUtils::GetElapsedSeconds ( PerfUtils::MomentValue start, PerfUtils::MomentValue finish )
98 {
99 	double startInSeconds = start.tv_sec + start.tv_nsec / 1000000000.0;
100 	double finishInSeconds = finish.tv_sec + finish.tv_nsec / 1000000000.0;
101 	return finishInSeconds - startInSeconds;
102 }	// PerfUtils::GetElapsedSeconds
103 
104 #endif
105 
106 // =================================================================================================
107 
108 #if XMP_MacBuild | XMP_iOSBuild
109 
110 #include <mach/mach.h>
111 #include <mach/mach_time.h>
112 
GetTimerInfo()113 const char * PerfUtils::GetTimerInfo()
114 {
115 	return "Mac PerfUtils measures nano seconds, using the mach_absolute_time() timer";
116 }	// PerfUtils::GetTimerInfo
117 
118 // ------------------------------------------------------------------------------------------------
119 
NoteThisMoment()120 PerfUtils::MomentValue PerfUtils::NoteThisMoment()
121 {
122 	return mach_absolute_time();
123 }	// PerfUtils::NoteThisMoment
124 
125 // ------------------------------------------------------------------------------------------------
126 
GetElapsedSeconds(PerfUtils::MomentValue start,PerfUtils::MomentValue finish)127 double PerfUtils::GetElapsedSeconds ( PerfUtils::MomentValue start, PerfUtils::MomentValue finish )
128 {
129 	static mach_timebase_info_data_t sTimebaseInfo;
130 	static double sConversionFactor = 0.0;
131 	// If this is the first time we've run, get the timebase.
132 	// We can use denom == 0 to indicate that sTimebaseInfo is
133 	// uninitialized because it makes no sense to have a zero
134 	// denominator is a fraction.
135 
136 	if ( sTimebaseInfo.denom == 0 ) {
137 		mach_timebase_info(&sTimebaseInfo);
138 		sConversionFactor = ((double)sTimebaseInfo.denom / (double)sTimebaseInfo.numer);
139 		sConversionFactor /= 1000000000.0;
140 	}
141 
142 	return ( finish - start ) * sConversionFactor;
143 }	// PerfUtils::GetElapsedSeconds
144 
145 #endif
146 
147 
148