Bug 1742472 - Use QueryProcessCycleTime on Windows to report total CPU time spent when the CPU has a constant TSC, r=gerald,jrmuizel.

Differential Revision: https://phabricator.services.mozilla.com/D131834
This commit is contained in:
Florian Queze 2021-11-24 10:46:45 +00:00
Родитель a2e85fcc9f
Коммит 5373598e93
3 изменённых файлов: 59 добавлений и 1 удалений

Просмотреть файл

@ -179,6 +179,8 @@ bool avx2_enabled = has_avx() && has_cpuid_bits(7u, ebx, (1u << 5));
bool aes_enabled = has_cpuid_bits(1u, ecx, (1u << 25));
# endif
bool has_constant_tsc = has_cpuid_bits(0x80000007u, edx, (1u << 8));
#endif
} // namespace sse_private

Просмотреть файл

@ -32,6 +32,7 @@
* mozilla::supports_avx
* mozilla::supports_avx2
* mozilla::supports_aes
* mozilla::has_constant_tsc
*
* If you're writing code using inline assembly, you should guard it with a
* call to one of these functions. For instance:
@ -223,6 +224,7 @@ extern bool MFBT_DATA avx2_enabled;
# if !defined(MOZILLA_PRESUME_AES)
extern bool MFBT_DATA aes_enabled;
# endif
extern bool MFBT_DATA has_constant_tsc;
#endif
} // namespace sse_private
@ -345,6 +347,12 @@ inline bool supports_aes() { return sse_private::aes_enabled; }
inline bool supports_aes() { return false; }
#endif
#ifdef MOZILLA_SSE_HAVE_CPUID_DETECTION
inline bool has_constant_tsc() { return sse_private::has_constant_tsc; }
#else
inline bool has_constant_tsc() { return false; }
#endif
} // namespace mozilla
#endif /* !defined(mozilla_SSE_h_) */

Просмотреть файл

@ -6,6 +6,7 @@
#include "mozilla/ProcInfo.h"
#include "mozilla/ipc/GeckoChildProcessHost.h"
#include "mozilla/SSE.h"
#include "nsMemoryReporterManager.h"
#include "nsNetCID.h"
#include "nsWindowsHelpers.h"
@ -18,14 +19,61 @@ typedef HRESULT(WINAPI* GETTHREADDESCRIPTION)(HANDLE hThread,
namespace mozilla {
uint64_t ToNanoSeconds(const FILETIME& aFileTime) {
static uint64_t ToNanoSeconds(const FILETIME& aFileTime) {
// FILETIME values are 100-nanoseconds units, converting
ULARGE_INTEGER usec = {{aFileTime.dwLowDateTime, aFileTime.dwHighDateTime}};
return usec.QuadPart * 100;
}
/* Get the CPU frequency to use to convert cycle time values to actual time.
* @returns the TSC frequency in MHz, or 0 if converting cycle time values
* should not be attempted. */
static int GetCycleTimeFrequency() {
static int result = -1;
if (result != -1) {
return result;
}
result = 0;
// Having a constant TSC is required to convert cycle time to actual time.
if (!mozilla::has_constant_tsc()) {
return result;
}
// Now get the nominal CPU frequency.
HKEY key;
static const WCHAR keyName[] =
L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0";
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyName, 0, KEY_QUERY_VALUE, &key) ==
ERROR_SUCCESS) {
DWORD data, len;
len = sizeof(data);
if (RegQueryValueEx(key, L"~Mhz", 0, 0, reinterpret_cast<LPBYTE>(&data),
&len) == ERROR_SUCCESS) {
result = static_cast<int>(data);
}
}
return result;
}
nsresult GetCpuTimeSinceProcessStartInMs(uint64_t* aResult) {
FILETIME createTime, exitTime, kernelTime, userTime;
int frequencyInMHz = GetCycleTimeFrequency();
if (frequencyInMHz) {
uint64_t cpuCycleCount;
if (!QueryProcessCycleTime(::GetCurrentProcess(), &cpuCycleCount)) {
return NS_ERROR_FAILURE;
}
constexpr int HZ_PER_MHZ = 1000000;
*aResult =
cpuCycleCount / (frequencyInMHz * (HZ_PER_MHZ / PR_MSEC_PER_SEC));
return NS_OK;
}
if (!GetProcessTimes(::GetCurrentProcess(), &createTime, &exitTime,
&kernelTime, &userTime)) {
return NS_ERROR_FAILURE;