Функция часов Python во FreeBSD
Во время тестирования функции Pythons time.clock() во FreeBSD я заметил, что она всегда возвращает одно и то же значение, около 0,156
Функция time.time() работает правильно, но мне нужно что-то с чуть более высоким разрешением.
У кого-нибудь есть функция C, к которой он привязан, и есть ли альтернативный таймер высокого разрешения?
Я не профилирую, поэтому модуль TimeIt здесь не совсем подходит.
4 ответа
time.clock() возвращает время процессора. То есть сколько времени текущий процесс использовал на процессоре. Так что, если у вас есть скрипт Python с именем "clock.py", это делает import time;print time.clock()
он действительно будет печатать примерно одинаково при каждом запуске, так как каждый раз запускается новый процесс.
Вот журнал консоли Python, который может вам это объяснить:
>>> import time
>>> time.clock()
0.11
>>> time.clock()
0.11
>>> time.clock()
0.11
>>> for x in xrange(100000000): pass
...
>>> time.clock()
7.7800000000000002
>>> time.clock()
7.7800000000000002
>>> time.clock()
7.7800000000000002
Я надеюсь, что это проясняет вещи.
Python time.clock вызывает функцию C clock(3) - man clock
должен подтвердить, что он должен работать на BSD, поэтому я не знаю, почему он не работает для вас. Может быть, вы можете попытаться обойти эту явную ошибку в вашем порту Python, используя ctypes
вызвать функцию clock напрямую из системной библиотеки C (если вы указали библиотеку как.so/.dynlib/.dll или какие-либо динамические общие библиотеки, вызываемые во FreeBSD)?
Кстати, time.time должен быть очень высокого разрешения, так как внутренне он вызывает gettimeofday (ну, в любом случае, в правильно построенном Python) - какое разрешение вы наблюдаете для него в вашей системе?
Редактировать: вот wat.c
специфичное для BSD расширение (протестировано только на моем Mac - извините, но у меня нет под рукой другого варианта BSD), чтобы обойти эту очевидную проблему с портом FreeBSD:
#include "Python.h"
#include <sys/time.h>
static PyObject *
wat_time(PyObject *self, PyObject *args)
{
struct timeval t;
if (gettimeofday(&t, (struct timezone *)NULL) == 0) {
double result = (double)t.tv_sec + t.tv_usec*0.000001;
return PyFloat_FromDouble(result);
}
return PyErr_SetFromErrno(PyExc_OSError);
}
static PyMethodDef wat_methods[] = {
{"time", wat_time, METH_VARARGS,
PyDoc_STR("time() -> microseconds since epoch")},
{NULL, NULL} /* sentinel */
};
PyDoc_STRVAR(wat_module_doc,
"Workaround for time.time issues on FreeBsd.");
PyMODINIT_FUNC
initwat(void)
{
Py_InitModule3("wat", wat_methods, wat_module_doc);
}
И вот setup.py
положить в тот же каталог:
from distutils.core import setup, Extension
setup (name = "wat",
version = "0.1",
maintainer = "Alex Martelli",
maintainer_email = "aleaxit@gmail.com",
url = "http://www.aleax.it/wat.zip",
description = "WorkAround for Time in FreeBSD",
ext_modules = [Extension('wat', sources=['wat.c'])],
)
URL-адрес правильный, поэтому вы также можете заархивировать эти два файла здесь.
Чтобы построить и установить это расширение, python setup.py install
(если у вас есть разрешение на запись в вашей установке Python) или python setup.py build_ext -i
написать wat.so в тот самый каталог, в который вы поместили исходники (а затем вручную переместите его туда, где вы предпочитаете, но сначала попробуйте, например, с помощью python -c'import wat; print repr(wat.time())'
в том же каталоге, в котором вы его построили).
Пожалуйста, дайте мне знать, как это работает на FreeBSD (или любой другой версии Unix с gettimeofday
!-) - если компилятор C жалуется на gettimeofday
, вы можете быть в системе, которая не хочет видеть свой второй аргумент, попробуйте без него!-).
time.clock()
возвращает время процессора в системах UNIX и время настенных часов с момента запуска программы в Windows. Это очень неудачная асимметрия, на мой взгляд.
Вы можете найти определение для time.time()
в источниках Python здесь (ссылка на Google Code Search). Кажется, он использует таймер с самым высоким разрешением, который, согласно быстрому поиску, gettimeofday()
на FreeBSD, и это должно быть в классе микросекундной точности.
Однако, если вам действительно нужна большая точность, вы можете заняться написанием своего собственного модуля C для синхронизации с действительно высоким разрешением (что-то, что может просто вернуть текущий счетчик микросекунд, возможно!). Pyrex делает написание Python расширения очень легким, и SWIG является другим распространенным выбором. (Хотя на самом деле, если вы хотите снизить точность таймера на столько же микросекунд, просто напишите это как расширение на чистом языке Python.) Ctypes также является опцией, но, вероятно, довольно медленной.
Удачи!
time.clock() реализован для возврата двойного значения, полученного в результате
((double)clock()) / CLOCKS_PER_SEC
Как вы думаете, почему у time.time() плохое разрешение? Он использует gettimeofday, который, в свою очередь, читает аппаратные часы, которые имеют очень хорошее разрешение.