MikeL has asked for the wisdom of the Perl Monks concerning the following question:

I have a Perl daemon running. It polls a set of rPi input pins, and checks for and replies to, incoming web URL requests. (The web requests are actually txt msgs via Plivo.) This app will run for months at a time. One of the requests returns me a txt with system info, including program and system uptime.

When I request the system info soon after a cold boot, the system uptime will reasonably be some 15 secs earlier than the program uptime. But after about a week, the program uptime will be larger than the system uptime, by about 15 mins! I have not spent effort characterizing this phenomena, but I have observed it several times now.

It's running on an rPi4 running "noobs", aka Linux. I'm using cpan Unix::Uptime->uptime() to get the system uptime, and am using (time - ^T) to get the program uptime.

Thoughts anyone?

Replies are listed 'Best First'.
Re: $BASETIME (^T) inaccurate?
by haukex (Archbishop) on Apr 11, 2023 at 06:59 UTC
    It's running on an rPi4

    Raspberry Pis don't have a Real-Time Clock with a backup battery, meaning on boot they have no idea what time it actually is, and they need to set the system time from an external source like an NTP server every time. time will change based on adjustments to the system time; if you're starting your script on boot or the system clock drifts and is adjusted by NTP during its runtime the measurement will be affected. If you want to know how long your script has actually been running in real-world time, independently of changes to the system clock, one way to do that is:

    use Time::HiRes qw/clock_gettime CLOCK_MONOTONIC/; my $start_time_s = clock_gettime(CLOCK_MONOTONIC); ... my $run_time_s = clock_gettime(CLOCK_MONOTONIC) - $start_time_s;

    See the documentation of clock_gettime for details - you may even want to use CLOCK_MONOTONIC_RAW depending on your requirements.

    Edit: Better link to manpage

Re: $BASETIME (^T) inaccurate?
by ikegami (Patriarch) on Apr 11, 2023 at 19:13 UTC

    $^T returns PL_basetime, which is obtained using the C code time(&PL_basetime) executed at startup.

    time returns the value returned by the C code time(NULL)

    So $^T - time is based on two readings of the clock obtained using time, which we know accurately returns the system time.

    On Linux, Unix::Uptime->uptime uses /proc/uptime.

    I don't know how this is calculated. If it's based on a counter counting ticks or similar, it wouldn't be based on the clock. Such an approach would result in a different amount than a difference in clock times if the clock is adjusted between the readings.

    Updated to add more.

Re: $BASETIME (^T) inaccurate?
by LanX (Saint) on Apr 11, 2023 at 02:42 UTC
    > the program uptime will be larger than the system uptime, by about 15 mins!

    It would help to know which of both has the accurate number.

    FWIW: Unix::Uptime::Linux seems to read from /proc/uptime

    Cheers Rolf
    (addicted to the 𐍀𐌴𐍂𐌻 Programming Language :)
    Wikisyntax for the Monastery

Re: $BASETIME (^T) inaccurate?
by Anonymous Monk on Apr 12, 2023 at 03:25 UTC

    Linux uptime accounts for changes in the system clock. That is: If you advance the clock 15minute, uptime advances its starting time by 15 minutes.

    $^T is simply the value of the time when your program started, and time is value of time now. So if the clock has advanced, the difference between these values will advance. Basically: deltas in perl 'time' cannot be used to judge time elapsed. They can only tell you what system clock was a two points.

      If you advance the clock 15minute, uptime advances its starting time by 15 minutes.

      and what happens if you "retard" the system clock? Perhaps you are confusing the first column in uptime's output (which is the current clock time) with the second column which is HH::MM of uptime? (Thank you Anonymous Re^2: $BASETIME (^T) inaccurate? for pointing this)

      If you advance the clock 15minute, uptime advances its starting time by 15 minutes.

      I dont think thats technically accurate, its just what it looks like. probably just uses a monotonic clock

Re: $BASETIME (^T) inaccurate?
by MikeL (Acolyte) on Apr 12, 2023 at 17:49 UTC
    I've made some temporary changes to the program to help work on this, namely at program startup it now saves the time of day, UnixUptime, and ^T value. I'll try to observe regularly and see what happens.

    Much of the discussion until now has been about how changing the system time could affect this. I assure you, I'm not changing the system time. ntpd could be getting involved, but that would only involve at most, tenths of seconds.

      I assure you, I'm not changing the system time. ntpd could be getting involved, but that would only involve at most, tenths of seconds.

      I explained that on a Raspberry Pi, NTP is most definitely involved (if connected to a network), and the time jumps are quite significant. Unless of course you've written your code in a way that it is not started on boot, but waits until the first time the NTP server is queried to start running, but you made no mention of that. You also mention "time of day, UnixUptime, and ^T value" but not the monotonic clock.

Re: $BASETIME (^T) inaccurate?
by MikeL (Acolyte) on May 18, 2023 at 17:13 UTC
    I've finally gotten this to do it again, and actually had time to look at it in detail.
    The program is started automatically at boot by /etc/rc.local
    At startup time, the program now saves in globals:
      AppStrtTime = time();
      AppStrtBasetime = $^T;
      UnixUpAtAppStrt = Unix::Uptime->uptime();

    The next afternoon I query the program and get:
      System uptime: (81700) 0d 22:41:40
      Program uptime: (82550) 0d 22:55:50
      UnixUpAtAppStrt: 27
      AppStrtTime: 1684095442
      AppStartBasetime: 1684095441
      time() now: 1684177991
      ^T now: 1684095441

    Armed with these numbers, reality check:
      UnixUpAtAppStrt = 27 -- sounds reasonable - boot to Perl app startup took half minute
      AppStrtTime follows within a second of AppStrtBasetime -- seems right as ^T was set when the app started, which would be before the code in the app actually started to execute and perform the time() call
      ^T now -- matches the ^T from startup, it has not changed

    With AppStrtTime time, and assuming UnixUpAtAppStrt was correct, the actual system startup time was:
      1684095442 - 27 = 1684095415
    Subtracting that from time now():
      1684177991 - 1684095415 = 82576
    yet:
      Unix::Uptime->uptime() = 81700
    WRONG! This should be 82576.
    If it was only a few seconds off, I wouldn't have even noticed, but it's off by 14+ mins in under 24 hours!

    Maybe some day I'll have a look at Unix::Uptime, but it may be a while - like years.
      too bad you didn't investigate the real reason this is happening: NTP.
        I'm really confident that it's not NTP causing the problem. The program sends me txt msgs throughout the day, including the time of day to seconds. I've never seen it appear to be out of whack. Doing a 'date' at the command line also seems accurate.

        Tell me this - if the command line time on the rPi is correct right now, and I do a 'shutdown -r now', when it restarts, would the time be way (15 mins) off?

        I did a vanilla noobs installation - doing a 'ps ax | grep ntp' I do not see NTPD running. This means that NTP is not changing the time under the running program, right? Does linux have some default occasional NTP run that I don't know about?

        Thanks for your thoughts!