-
-
Notifications
You must be signed in to change notification settings - Fork 34.7k
bpo-31415: Add _PyTime_GetPerfCounter() and use it for -X importtime #3936
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -285,8 +285,8 @@ _PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv, int raise) | |
| #endif | ||
|
|
||
| static int | ||
| _PyTime_FromFloatObject(_PyTime_t *t, double value, _PyTime_round_t round, | ||
| long unit_to_ns) | ||
| _PyTime_FromDouble(_PyTime_t *t, double value, _PyTime_round_t round, | ||
| long unit_to_ns) | ||
| { | ||
| /* volatile avoids optimization changing how numbers are rounded */ | ||
| volatile double d; | ||
|
|
@@ -315,7 +315,7 @@ _PyTime_FromObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round, | |
| PyErr_SetString(PyExc_ValueError, "Invalid value NaN (not a number)"); | ||
| return -1; | ||
| } | ||
| return _PyTime_FromFloatObject(t, d, round, unit_to_ns); | ||
| return _PyTime_FromDouble(t, d, round, unit_to_ns); | ||
| } | ||
| else { | ||
| long long sec; | ||
|
|
@@ -779,19 +779,80 @@ _PyTime_GetMonotonicClockWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) | |
| return pymonotonic(tp, info, 1); | ||
| } | ||
|
|
||
|
|
||
| #ifdef MS_WINDOWS | ||
| int | ||
| _PyTime_Init(void) | ||
| _PyTime_GetWinPerfCounterWithInfo(_PyTime_t *t, _Py_clock_info_t *info) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And this accepted a
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. +1 |
||
| { | ||
| static LONGLONG cpu_frequency = 0; | ||
| static LONGLONG ctrStart; | ||
| LARGE_INTEGER now; | ||
| double diff; | ||
|
|
||
| if (cpu_frequency == 0) { | ||
| LARGE_INTEGER freq; | ||
| QueryPerformanceCounter(&now); | ||
| ctrStart = now.QuadPart; | ||
| if (!QueryPerformanceFrequency(&freq) || freq.QuadPart == 0) { | ||
| PyErr_SetFromWindowsErr(0); | ||
| return -1; | ||
| } | ||
| cpu_frequency = freq.QuadPart; | ||
| } | ||
| QueryPerformanceCounter(&now); | ||
| diff = (double)(now.QuadPart - ctrStart); | ||
| if (info) { | ||
| info->implementation = "QueryPerformanceCounter()"; | ||
| info->resolution = 1.0 / (double)cpu_frequency; | ||
| info->monotonic = 1; | ||
| info->adjustable = 0; | ||
| } | ||
|
|
||
| diff = diff / (double)cpu_frequency; | ||
| return _PyTime_FromDouble(t, diff, _PyTime_ROUND_FLOOR, SEC_TO_NS); | ||
| } | ||
| #endif | ||
|
|
||
|
|
||
| int | ||
| _PyTime_GetPerfCounterWithInfo(_PyTime_t *t, _Py_clock_info_t *info) | ||
| { | ||
| #ifdef MS_WINDOWS | ||
| return _PyTime_GetWinPerfCounterWithInfo(t, info); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And the call to It wouldn't be ideal, since the #ifdef logic would exist in two places, but maybe that duplication could be handled via a common macro definition that was used in both places, rather than by incurring the redundant conversion at runtime on Windows. |
||
| #else | ||
| return _PyTime_GetMonotonicClockWithInfo(t, info); | ||
| #endif | ||
| } | ||
|
|
||
|
|
||
| _PyTime_t | ||
| _PyTime_GetPerfCounter(void) | ||
| { | ||
| _PyTime_t t; | ||
| if (_PyTime_GetPerfCounterWithInfo(&t, NULL) < 0) { | ||
| /* should not happen, _PyTime_Init() checked the clock at startup */ | ||
| Py_UNREACHABLE(); | ||
| } | ||
| return t; | ||
| } | ||
|
|
||
| /* ensure that the system clock works */ | ||
| if (_PyTime_GetSystemClockWithInfo(&t, NULL) < 0) | ||
| return -1; | ||
|
|
||
| /* ensure that the operating system provides a monotonic clock */ | ||
| if (_PyTime_GetMonotonicClockWithInfo(&t, NULL) < 0) | ||
| int | ||
| _PyTime_Init(void) | ||
| { | ||
| /* check that the 3 most important clocks are working properly | ||
| to not have to check for exceptions at runtime. If a clock works once, | ||
| it cannot fail in next calls. */ | ||
| _PyTime_t t; | ||
| if (_PyTime_GetSystemClockWithInfo(&t, NULL) < 0) { | ||
| return -1; | ||
|
|
||
| } | ||
| if (_PyTime_GetMonotonicClockWithInfo(&t, NULL) < 0) { | ||
| return -1; | ||
| } | ||
| if (_PyTime_GetPerfCounterWithInfo(&t, NULL) < 0) { | ||
| return -1; | ||
| } | ||
| return 0; | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Idea for avoiding the redundant
double->_PyTime_t->doubleconversion intime.perf_counter():What if this still kept a compile time conditional branch between the Windows API and the *nix one?