2013-03-23 15 views
7

リストから繰り返しメッセージをすばやく正確に送信する必要があります。 1つのリストは、100msごとに+/- 10msのウィンドウでメッセージを送信する必要があります。私は以下のコードを使用してみましたが、問題はタイマーが100ms待機してから、すべての計算を行う必要があり、タイマーを許容可能なウィンドウから外すことです。単に待ち時間を減らす高速で正確なPython繰返しタイマー

は汚いし、信頼できないハックです。ループ中にリストが編集されるイベントでは、メッセージループの周りにLockがあります。 Pythonは100msの周りを一貫してメッセージを送信するために取得する方法について

思考?ありがとう

from threading import Timer 
from threading import Lock 

class RepeatingTimer(object): 
    def __init__(self,interval, function, *args, **kwargs): 
     super(RepeatingTimer, self).__init__() 
     self.args = args 
     self.kwargs = kwargs 
     self.function = function 
     self.interval = interval 
     self.start() 

    def start(self): 
     self.callback() 

    def stop(self): 
     self.interval = False 

    def callback(self): 
     if self.interval: 
      self.function(*self.args, **self.kwargs) 
      Timer(self.interval, self.callback,).start() 

def loop(messageList): 
    listLock.acquire() 
    for m in messageList: 
     writeFunction(m) 
    listLock.release() 


MESSAGE_LIST = [] #Imagine this is populated with the messages 
listLock = Lock() 
rt = RepeatingTimer(0.1,loop,MESSAGE_LIST) 
#Do other stuff after this 

私はwriteFunctionがいくつかの遅延を引き起こしますが、10msを超えないことを理解しています。私は本質的に、各メッセージに対して100msごとに関数を呼び出す必要があります。 messagelistは小さく、通常要素よりも小さい。 P

+0

その1 :( –

答えて

0

ストア開始時刻:

次の課題は、10ms毎にこの作品、+/- 1ミリ秒を持っていることです。メッセージを送信します。終了時間を取得します。 timeTaken = end-startを計算します。 FP秒に変換します。睡眠(0.1時間経過)。ループバック。

8

はい、簡単な待ち時間は厄介で、より良い選択肢があります。

まず第一に、あなたはPythonで高精度のタイマーを必要とします。いくつかの選択肢があり、お使いのOSによっては、the most accurate oneを選択することもできます。

第2に、basics preemptive multitaskingを認識し、高精度のsleep機能がないこと、および実際の解像度がOSによって異なることも理解する必要があります。たとえば、Windowsの場合は、the minimal sleep interval might be around 10-13 msです。

そして第三が、高いCPU負荷のトレードオフで、それは(あなたが高解像度のタイマーを持っていると仮定して)時間の非常に正確な間隔を待つことが常に可能だということを覚えておいてください。技術はbusy waitingと呼ばれている:

while(True): 
    if time.clock() == something: 
     break 

ので、実際のソリューションは、ハイブリッドのタイマーを作成することです。通常のsleep関数を使用してインターバルの大部分を待機させ、sleep(0)トリックを実行しながらループ内の高精度タイマーのプロービングを開始します。 Sleep(0)(プラットフォームによって異なる)は可能な限りの時間を待って残りの残りのタイムスライスを他のプロセスに解放し、CPUコンテキストを切り替えます。関連するdiscussionがここにあります。

アイデアを徹底的ライアンGeissのTiming in Win32資料に記載されています。これはC言語とWindows API用ですが、ここでも基本原則が適用されます。

+2

と幸運「10ms毎に、+/- 1ミリ秒との仕事」は、それがより安全time.clockをチェックすることではありません()> =何か私が思います? "time.clock()"が少し "何か"にジャンプするリスクがあることを確認してください – vac

+0

空想的な 'busy waiting'ラベルに惑わされないでください。可能な限り避ける必要があります。 – jjmontes

0

これを試してみてください。

#!/usr/bin/python 
import time; # This is required to include time module. 
from threading import Timer 

def hello(start, interval, count): 
    ticks = time.time() 
    t = Timer(interval - (ticks-start-count*interval), hello, [start, interval, count+1]) 
    t.start() 
    print "Number of ticks since 12:00am, January 1, 1970:", ticks, " #", count 

dt = 1.25 # interval in sec 
t = Timer(dt, hello, [round(time.time()), dt, 0]) # start over at full second, round only for testing here 
t.start() 
関連する問題