summaryrefslogtreecommitdiff
path: root/source/PerfUtils.cpp
blob: f792f73b13ef2436357e0fea72e8116fe65e59a2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// =================================================================================================
// Copyright 2006 Adobe
// All Rights Reserved.
//
// NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the terms
// of the Adobe license agreement accompanying it. If you have received this file from a source other 
// than Adobe, then your use, modification, or distribution of it requires the prior written permission
// of Adobe.
// =================================================================================================

#include "public/include/XMP_Environment.h"
#include "public/include/XMP_Const.h"

#include "source/PerfUtils.hpp"

#include <stdio.h>

#if XMP_WinBuild
	#pragma warning ( disable : 4996 )	// '...' was declared deprecated
#endif

// =================================================================================================
// =================================================================================================

#if XMP_WinBuild

#pragma warning ( disable : 4800 )	// forcing bool to 0/1

const char * PerfUtils::GetTimerInfo()
{
	LARGE_INTEGER freq;
	static char msgBuffer[1000];

	bool ok = (bool) QueryPerformanceFrequency ( &freq );
	if ( ! ok ) throw XMP_Error ( kXMPErr_ExternalFailure, "Failure from QueryPerformanceFrequency" );
	
	if ( freq.HighPart != 0 ) {
		return "Windows PerfUtils measures finer than nanoseconds, using the QueryPerformanceCounter() timer";
	}
	
	double rate = 1.0 / (double)freq.LowPart;
	_snprintf ( msgBuffer, sizeof(msgBuffer),
			   "Windows PerfUtils measures %e second, using the QueryPerformanceCounter() timer", rate );
	return msgBuffer;
	
}	// PerfUtils::GetTimerInfo

// ------------------------------------------------------------------------------------------------

PerfUtils::MomentValue PerfUtils::NoteThisMoment()
{
	LARGE_INTEGER now;

	bool ok = (bool) QueryPerformanceCounter ( &now );
	if ( ! ok ) throw XMP_Error ( kXMPErr_ExternalFailure, "Failure from QueryPerformanceCounter" );
	return now.QuadPart;

}	// PerfUtils::NoteThisMoment

// ------------------------------------------------------------------------------------------------

double PerfUtils::GetElapsedSeconds ( PerfUtils::MomentValue start, PerfUtils::MomentValue finish )
{
	LARGE_INTEGER freq;

	bool ok = (bool) QueryPerformanceFrequency ( &freq );
	if ( ! ok ) throw XMP_Error ( kXMPErr_ExternalFailure, "Failure from QueryPerformanceFrequency" );

	const double scale = (double)freq.QuadPart;
	
	const double elapsed = (double)(finish - start) / scale;
	return elapsed;

}	// PerfUtils::GetElapsedSeconds

#endif

// =================================================================================================

#if XMP_UNIXBuild | XMP_AndroidBuild

const char * PerfUtils::GetTimerInfo()
{
	return "UNIX PerfUtils measures nano seconds, using the POSIX clock_gettime() timer";
}	// PerfUtils::GetTimerInfo

// ------------------------------------------------------------------------------------------------

PerfUtils::MomentValue PerfUtils::NoteThisMoment()
{
	MomentValue moment = kZeroMoment;
	if ( clock_gettime( CLOCK_MONOTONIC, &moment ) != 0 )
		throw XMP_Error( kXMPErr_ExternalFailure, "Failure from clock_gettime" );
	return moment;
}	// PerfUtils::NoteThisMoment

// ------------------------------------------------------------------------------------------------

double PerfUtils::GetElapsedSeconds ( PerfUtils::MomentValue start, PerfUtils::MomentValue finish )
{
	double startInSeconds = start.tv_sec + start.tv_nsec / 1000000000.0;
	double finishInSeconds = finish.tv_sec + finish.tv_nsec / 1000000000.0;
	return finishInSeconds - startInSeconds;
}	// PerfUtils::GetElapsedSeconds

#endif

// =================================================================================================

#if XMP_MacBuild | XMP_iOSBuild

#include <mach/mach.h>
#include <mach/mach_time.h>

const char * PerfUtils::GetTimerInfo()
{
	return "Mac PerfUtils measures nano seconds, using the mach_absolute_time() timer";
}	// PerfUtils::GetTimerInfo

// ------------------------------------------------------------------------------------------------

PerfUtils::MomentValue PerfUtils::NoteThisMoment()
{
	return mach_absolute_time();
}	// PerfUtils::NoteThisMoment

// ------------------------------------------------------------------------------------------------

double PerfUtils::GetElapsedSeconds ( PerfUtils::MomentValue start, PerfUtils::MomentValue finish )
{
	static mach_timebase_info_data_t sTimebaseInfo;
	static double sConversionFactor = 0.0;
	// If this is the first time we've run, get the timebase.
	// We can use denom == 0 to indicate that sTimebaseInfo is 
	// uninitialized because it makes no sense to have a zero 
	// denominator is a fraction.

	if ( sTimebaseInfo.denom == 0 ) {
		mach_timebase_info(&sTimebaseInfo);
		sConversionFactor = ((double)sTimebaseInfo.denom / (double)sTimebaseInfo.numer);
		sConversionFactor /= 1000000000.0;
	}

	return ( finish - start ) * sConversionFactor;
}	// PerfUtils::GetElapsedSeconds

#endif