From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=unavailable autolearn_force=no version=3.4.4 Path: eternal-september.org!reader01.eternal-september.org!reader02.eternal-september.org!news.eternal-september.org!mx02.eternal-september.org!feeder.eternal-september.org!aioe.org!.POSTED!not-for-mail From: Emanuel Berg Newsgroups: comp.lang.ada Subject: Re: how to analyze clock drift Date: Sun, 23 Nov 2014 21:15:05 +0100 Organization: Aioe.org NNTP Server Message-ID: <8761e54qt2.fsf@debian.uxu> References: <6uun6alsp3jh1pob6g9qgcg85etqgenmd0@4ax.com> <87zjbn3nss.fsf@debian.uxu> <1nvfhit2csxr5.41v36jksch28$.dlg@40tude.net> <87k32qet5y.fsf@debian.uxu> <188uppnlnvqgq$.1kjz3jnhjxqji.dlg@40tude.net> <87fvdd38qi.fsf@debian.uxu> <87a93l35dm.fsf@debian.uxu> <9t7t6al8bmifd9krh6koiegttgsvcovadg@4ax.com> <87d28h1cj9.fsf@debian.uxu> <3apu6ap126abi6oalch9vpre20hjij2uon@4ax.com> <87k32oi7r8.fsf@debian.uxu> <98h17atrhtl9kitthjf8ukt1f7rk1ribvc@4ax.com> NNTP-Posting-Host: feB02bRejf23rfBm51Mt7Q.user.speranza.aioe.org Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Complaints-To: abuse@aioe.org User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.4 (gnu/linux) X-Notice: Filtered by postfilter v. 0.8.2 Cancel-Lock: sha1:85MxihdmBCt8UMtqfaOagXCCYT8= Mail-Copies-To: never Xref: news.eternal-september.org comp.lang.ada:23673 Date: 2014-11-23T21:15:05+01:00 List-Id: Dennis Lee Bieber writes: >> Are you saying: >> >> 1. we know that sleep_until isn't perfect - it can >> sleep longer than x, for an argument x, as the docs >> say >> >> 2. I am attempting to log the error of sleep_until >> with now() but that can't be done as now() uses the >> same technology and thus can likewise be incorrect >> >> *Or*, are you saying: >> >> we can't trust now() *at all* because it invokes an >> OS routine which can give it whatever data? >> > All three apply. You can not use the system clock to > measure errors in the system clock. > > Sleep_Until may be off by one system tick (which > itself may be a rather large quantity -- 15.6mSec is > common in Windows OS, though I believe privileged > code can change that); Sleep_Until and Now are both > using the same clock, so if the clock ran slow > (meaning the sleep runs longer than nominal), Now > will report the slow time value -- not the real time > that is longer; and Now may be affected by any > background updates of the system time (NTP updates, > for example). > > At the least, you need to know the granularity at > which "now" is updated, as that is likely to also be > the granularity at which sleep_until triggers. > > System time is determined by some counter (of ticks) > divided by some constant representing the expected > ticks per second (TPS). Regardless of how the clock > is varying, it will report that one second has > passed when TPS ticks have been counted. (Worse, the > OS ticks are, themselves, based upon some number of > hardware clock cycles OR some external clock > interrupt -- given that my current systems have a > "turbo boost" in which all but one core is halted > while the running core gets clocked much faster, > having the system tick based on the CPU clock > frequency would be hairy) > > In order to determine clock drift, you must measure > how many ticks really took place relative to an > external time-base (which is presumed to be "truth" > -- eg; a 1 pulse-per-second output from a cesium > time-base [atomic clock]). You would read the system > clock value each time the external time base pulses > some interrupt line (or you use a tight polling > loop). You also need to know the system's defined > value for TPS. > > (apologies for another M$ reference -- worse, .NET > specific, and the .NET runtime may be doing some > other translations from the hardware and OS clock > ticks. -- on Windows you could expect to see the > clock value update in jumps of 156000 ticks -- > unless it internally calls some other counter to get > finer resolution) > > http://msdn.microsoft.com/en-us/library/system.timespan.tickspersecond%28v=vs.110%29.aspx > > That 15.6mSec would also affect the jitter in your > measurements as you could start a delay at either > just before an update or just after the update -- > that means 15mSec of potential variance. > > Borrowing from the Python documentation: """ > time.clock() On Unix, return the current processor > time as a floating point number expressed in > seconds. The precision, and in fact the very > definition of the meaning of “processor time”, > depends on that of the C function of the same name, > but in any case, this is the function to use for > benchmarking Python or timing algorithms. > > On Windows, this function returns wall-clock seconds > elapsed since the first call to this function, as a > floating point number, based on the Win32 function > QueryPerformanceCounter(). The resolution is > typically better than one microsecond. """ """ > time.sleep(secs) Suspend execution for the given > number of seconds. The argument may be a floating > point number to indicate a more precise sleep time. > The actual suspension time may be less than that > requested because any caught signal will terminate > the sleep() following execution of that signal’s > catching routine. Also, the suspension time may be > longer than requested by an arbitrary amount because > of the scheduling of other activity in the system. > """ """ time.time() Return the time in seconds since > the epoch as a floating point number. Note that even > though the time is always returned as a floating > point number, not all systems provide time with a > better precision than 1 second. While this function > normally returns non-decreasing values, it can > return a lower value than a previous call if the > system clock has been set back between the two > calls. """ > > In Python, to do really fine sleeps requires using a > busy loop as the system sleep routine is too coarse > (especially in Windows) -- and it makes delay-until > tricky to implement as time.clock() is not > wall-clock related. > > Note that the Python clock() call, on Windows > systems, is not using the system clock, but rather > the finer resolution performance counters -- but the > sleep() call is implied to be using the system clock > [Python doesn't implement a sleep_until()]. > >> If you are saying the second, I think it is assumed >> that the system time is an adequate measure of >> physical (perfect) time. So the ideal time I >> describe above is assumed to be what is outputted >> by now, and that is assumed to be a adequately >> correct reading of how much the delay (sleep_until) >> actually sleep, i.e. its drift from the desired >> perfect periodicity. > > Let me try to put this into a more physical > example... An old fashioned alarm clock... > > Set the alarm for, say, 6AM (this is the > Delay_Until). Now, when the alarm goes off, you read > the clock face to determine when it went off... The > clock will show 6AM -- even if the clock is losing > one minute per hour. After two days, the clock still > shows the alarm going off at 6AM, but it is going > off 48 minutes away from a standard clock. > > What your numbers are showing, to the best of my > interpretation, is the equivalent of you going > somewhere else in your house and waiting for the > delay to expire (the alarm goes off), and then > running through the house to get to the room with > the clock and reading the face and using /that/ as > the time it went off (6:02 if you had to navigate a > few floors) ("that" is the latency from when the OS > detected the delay expired and rescheduled the tast > through to when the read operation captured the > clock value). That's a lot to digest :) But I understand the last example, and that is how I thought about it all along. So I'll keep the section in the report as it stands. But I should add another paragraph explaining "it is complicated", or at least change the terminology before the examination (mine) so people won't think I do the kind of clock analysis that you describe (with an external atomic clock), and be all confused about it (them, or them thinking me, or both). I never intended to do something like that and that's where the confusion started. So if I leave it as it is it is likely people will be confused once more the exact same way. So instead of having the terms drift and jitter - or can I have them? - I should say, in your words: > the latency from when the OS detected the delay > expired and rescheduled the tast through to when the > read operation captured the clock value I can explain that, and then add like, "If you were to employ this system in a critical setting, it would be necessary to have a much more reliable clock to trigger the interrupts. Although you can have widely diverging results due to many factors, to illustrate the lack of periodicity, and to some degree how that behaves and fluctuates [I'm referring to the stats here], run the program with `-l' and study the outputs..." (I'm not going to put it exactly like that, but you get the idea.) Is that better? -- underground experts united