Функция синхронизации Python во FreeBSD
-
12-09-2019 - |
Вопрос
Во время тестирования функции Pythons time.clock() на FreeBSD я заметил, что она всегда возвращает одно и то же значение, около 0,156
Функция time.time() работает должным образом, но мне нужно что-то с немного более высоким разрешением.
Есть ли у кого-нибудь функция C, к которой она привязана, и есть ли альтернативный таймер высокого разрешения?
Я не занимаюсь профилированием, поэтому модуль TimeIt здесь не совсем уместен.
Решение
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
Я надеюсь, что это кое-что прояснит.
Другие советы
Time.clock в Python вызывает функцию C clock(3) -- man clock
должен подтвердить, что это должно работать на BSD, поэтому я не знаю, почему это не работает у вас.Возможно, вы можете попробовать обойти эту очевидную ошибку в вашем порту Python, используя ctypes
вызвать функцию clock напрямую из системной библиотеки C (если вы указали библиотеку как a .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).Похоже, что он использует доступный таймер с самым высоким разрешением, который, согласно быстрому поиску в Google, является gettimeofday()
во FreeBSD тоже, и это должно соответствовать классу точности в микросекунду.
Однако, если вам действительно нужна большая точность, вы могли бы подумать о написании собственного модуля C для синхронизации с действительно высоким разрешением (возможно, что-то, что могло бы просто возвращать текущее количество микросекунд!). Пирекс упрощает написание расширений на Python и ГЛОТОК это другой распространенный выбор.(Хотя на самом деле, если вы хотите снизить точность вашего таймера на как можно больше микросекунд, просто напишите его как чистое расширение C Python самостоятельно.) Ctypes также является вариантом, но, вероятно, довольно медленным.
Желаю удачи!
time.clock() реализован для возврата двойного значения, полученного в результате
((double)clock()) / CLOCKS_PER_SEC
Как вы думаете, почему time.time() имеет плохое разрешение?Он использует gettimeofday, который, в свою очередь, считывает аппаратные часы, которые имеют очень хорошее разрешение.