[Twisted-Python] accurate periodic call

Zoran Bošnjak Zoran.Bosnjak at sloveniacontrol.si
Wed Mar 14 07:57:02 EDT 2012


Hello all,
Thanks for all your comments.

I have filed a ticket regarding this issue:
http://twistedmatrix.com/trac/ticket/5552

I hope it will be accepted as a problem.

regards,
Zoran

________________________________________
From: twisted-python-bounces at twistedmatrix.com [twisted-python-bounces at twistedmatrix.com] on behalf of Zoran Bošnjak [Zoran.Bosnjak at sloveniacontrol.si]
Sent: Sunday, February 19, 2012 5:49 PM
To: twisted-python at twistedmatrix.com
Subject: [Twisted-Python] accurate periodic call

Hello all,
I was astonished to find out that looping call period depends on the system time by default. The periodic tick can even stall for a long time, if the system time jumps backwards during program execution. It turned out that this is in fact a python problem (not providing a monotonic time, at least not for posix).

I urgently need accurate periodic call in my program and I've found the solution below that seems to be working. I kindly ask you for your comments:
- Is this monotonic_time implementation OK from python perspective?
- Is monkey patch to the reactor OK or is there any other solution more appropriate in this case (I do not want to patch each looping call, but once in the application)?
- Does this patch have any negative influence to the rest of the reactor?
- How would you implement a periodic function call in twisted application (as accurate as possible)?
- Any chance to see something implemented inside twisted and/or python, so that applications don't need this kind of tricks?

Thanks a lot for your comments.

Zoran

#! /usr/bin/env python

from twisted.internet import task
from twisted.internet import reactor
import os
import time
import ctypes

# python MONOTONIC time, borrowed here
# http://stackoverflow.com/questions/1205722/how-do-i-get-monotonic-time-durations-in-python
if os.name == 'posix':

    CLOCK_MONOTONIC = 1 # see <linux/time.h>

    class timespec(ctypes.Structure):
        _fields_ = [
            ('tv_sec', ctypes.c_long),
            ('tv_nsec', ctypes.c_long)
        ]

    librt = ctypes.CDLL('librt.so.1', use_errno=True)
    clock_gettime = librt.clock_gettime
    clock_gettime.argtypes = [ctypes.c_int, ctypes.POINTER(timespec)]

    def monotonic_time():
        t = timespec()
        if clock_gettime(CLOCK_MONOTONIC, ctypes.pointer(t)) != 0:
            errno_ = ctypes.get_errno()
            raise OSError(errno_, os.strerror(errno_))
        return t.tv_sec + t.tv_nsec * 1e-9

    # monkey patch the reactor
    reactor.seconds = monotonic_time

# TODO: check for other platforms!!
else:
    monotonic_time = time.time

def tick():
    """This function is suppose to execute once a second,
    regardless of the system time."""

    print 'tick', monotonic_time()

loop = task.LoopingCall(tick)
loop.start(1.0)

reactor.run()

_______________________________________________
Twisted-Python mailing list
Twisted-Python at twistedmatrix.com
http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python



More information about the Twisted-Python mailing list