summaryrefslogtreecommitdiffstats
path: root/Whisper/Utils/CpuProfiler.cpp
blob: 6161e95ae29831e898a7395246984e1c49097c37 (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
#include "stdafx.h"
#include "CpuProfiler.h"

namespace
{
	using namespace Whisper;

	inline int64_t qpcNow()
	{
		int64_t res;
		QueryPerformanceCounter( (LARGE_INTEGER*)&res );
		return res;
	}

	class CpuTimescale
	{
		uint64_t frequency = 0;
		const int64_t tscStart;
		const int64_t qpcStart;

		uint64_t computeTscFrequency();

	public:

		CpuTimescale() :
			tscStart( tscNow() ),
			qpcStart( qpcNow() )
		{ }

		inline uint64_t computeTicks( uint64_t tsc )
		{
			uint64_t freq = frequency;
			if( freq == 0 )
				freq = computeTscFrequency();

			return makeTime( tsc, freq );
		}
	};

	uint64_t __declspec( noinline ) CpuTimescale::computeTscFrequency()
	{
		int64_t tsc = tscNow();
		int64_t qpc = qpcNow();
		tsc -= tscStart;
		qpc -= qpcStart;

		uint64_t qpcFreq;
		QueryPerformanceFrequency( (LARGE_INTEGER*)&qpcFreq );

		// Seconds = qpc / qpcFreq
		// ticks per second = tsc / seconds = tsc * qpcFreq / qpc
		uint64_t res = ( (uint64_t)tsc * qpcFreq + ( (uint64_t)qpc / 2 ) - 1 ) / (uint64_t)qpc;
		frequency = res;
		const double GHz = (double)(int64_t)res * 1.0E-9;
		logDebug( u8"Computed CPU base frequency: %g GHz", GHz );
		return res;
	}

	static CpuTimescale timescale;
}

uint64_t Whisper::ticksFromTsc( uint64_t tscDiff )
{
	return timescale.computeTicks( tscDiff );
}