summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2017-10-10 09:51:50 (GMT)
committerGitHub <noreply@github.com>2017-10-10 09:51:50 (GMT)
commita997c7b434631f51e00191acea2ba6097691e859 (patch)
tree1626ff43ab1ace99e035474b1727a08f22e65404 /Python
parent14aa00b519c827578648f2c006ad0ac8058cf6a1 (diff)
downloadcpython-a997c7b434631f51e00191acea2ba6097691e859.zip
cpython-a997c7b434631f51e00191acea2ba6097691e859.tar.gz
cpython-a997c7b434631f51e00191acea2ba6097691e859.tar.bz2
bpo-31415: Add _PyTime_GetPerfCounter() and use it for -X importtime (#3936)
* Add _PyTime_GetPerfCounter() * Use _PyTime_GetPerfCounter() for -X importtime
Diffstat (limited to 'Python')
-rw-r--r--Python/import.c4
-rw-r--r--Python/pytime.c81
2 files changed, 73 insertions, 12 deletions
diff --git a/Python/import.c b/Python/import.c
index 7554bf8..d396b4d 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -1695,7 +1695,7 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals,
if (ximporttime) {
import_level++;
- t1 = _PyTime_GetMonotonicClock();
+ t1 = _PyTime_GetPerfCounter();
accumulated = 0;
}
@@ -1711,7 +1711,7 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals,
mod != NULL);
if (ximporttime) {
- _PyTime_t cum = _PyTime_GetMonotonicClock() - t1;
+ _PyTime_t cum = _PyTime_GetPerfCounter() - t1;
import_level--;
fprintf(stderr, "import time: %9ld | %10ld | %*s%s\n",
diff --git a/Python/pytime.c b/Python/pytime.c
index 8f275d2..bda6d8b 100644
--- a/Python/pytime.c
+++ b/Python/pytime.c
@@ -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)
+{
+ 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);
+#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;
}