Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

is is.clock real time or CPU time? I need elapsed subsecond timing

I'd like to have an event happening every 1/4 second. os.time turns over once a second. os.clock is subsecond but is described as "CPU time". Is it that, or is it elapsed time? If it's CPU time, is the a way to get wall clock fractional seconds?

Thanks!

Comments

  • dave1707dave1707 Mod
    Posts: 8,723

    @RonJeffries Use tween delay to execute a function every .25 seconds.

    viewer.mode=STANDARD
    
    function setup() 
        start=true
        count=0
    end
    
    function draw()
        background(0)
        if start then
            start=false
            count=count+1
            tween.delay(.25,run)
        end
    end
    
    function run()
        print(count)
        start=true
    end
    
  • @dave1707 That's not 1/4s on the wall clock though. That's every 1/4s since the program started, and it will also gradually drift as it runs at it has to wait for the next frame before updating.

    @RonJeffries If I've understood you correctly, here's some code that I have to achieve that end. It combines os.date(), which is wall time accurate to the second, with ElapsedTime, which is millisecond accurate but counts since the start of the program.

    Basically, we try to get an accurate reading on ElapsedTime when os.date() clicks over from one second to the next. This then allows us to use ElapsedTime to calculate the current millisecond reading and thus provide an accurate timestamp.

    The difficulty is that we can only examine our "clocks" each frame. This makes it complicated as we can't tell exactly when os.date() clicks over from one second to the next.

    I actually wrote this up for the Big Lockdown Math-Off (scroll down half way, also ignore the results of the vote!).

    Here's the code. We want to note the exact ElapsedTime when os.date() ticks over from one second to the next. All we can actually say is that it happened between one frame and the next which gives us an upper and lower limit on the millisecond reading. By continually readjusting, we can zero in on the actual reading.

    Here's some code:

    local __l = 0
    local __h = 1
    local __psec
    local __pet
    
    function Now()
      local t = os.date("*t")
      local et = ElapsedTime
      if __psec ~= nil and t.sec ~= __psec then
        local a,b = __pet - math.floor(__pet), et - math.floor(__pet)
        if b - a < .5 then
            if __l + 1 < b then
              a,b = a-1, b-1
            end
            __l = math.max(__l,a)
            __h = math.max(__h,b)
        end
      end
      lower = __l
      higher = __h
      __pet = et
      __psec = t.sec
      et = et - (__l + __h)/2
      local time = {}
      time.msec = (et - math.floor(et))*1000
      time.sec = t.sec
      time.min = t.min
      time.hour = t.hour
      time.yday = t.yday
      return time
    end
    
  • dave1707dave1707 Mod
    edited December 2020 Posts: 8,723

    @LoopSpace Looking at the first post, @RonJeffries didn’t say how exact he wanted it to be over a long of a period of time. That’s why I just chose tween delay. If it needs to be almost exact over a long period (according to the wall clock), I think this code will work. It uses the socket “gettime” function which I think is pretty accurate to several decimal places.

    The time interval can be changed in the call to checkDuration(). This code prints the gettime every .25 seconds.

    viewer.mode=STANDARD
    
    function setup() 
        s=require("socket")
        st=s:gettime()
        c=0
    end
    
    function draw()
        background(0)
        checkDuration(.25)
    end
    
    function checkDuration(d)
        local i=s:gettime()-st
        if i>c then
            c=c+d
            xx()
        end
    end
    
    function xx()
        print(s:gettime())
    end
    
  • and i completely forgot ElapsedTime, which really ought to be mentioned in the time tab of the docs. :smiley:

  • @LoopSpace neat ... far more than i needed. and res, @dave1707, maybe tween delay will be better. thanks for reminder. i think my head was empty today.

  • dave1707dave1707 Mod
    Posts: 8,723

    ElapsedTime isn’t that reliable if the FPS starts to drop. Here’s an example. Slide the slider and see what happens to the ElapsedTime that’s displayed.

    viewer.mode=STANDARD
    
    function setup() 
        parameter.integer("delay",1,10000)
    
    end
    
    function draw()
        background(0)
        for z=1,delay*10000 do
            a=math.sqrt(z)
        end
        text(ElapsedTime,WIDTH/2,HEIGHT/2)
    end
    
  • hm, weird. tweens are easy enough, i guess i'll go that way.

  • dave1707dave1707 Mod
    Posts: 8,723

    Here’s an example of executing different functions at different time intervals.

    viewer.mode=STANDARD
    
    function setup()
        t1=checkDelay(.3)
        t2=checkDelay(.5)
        t3=checkDelay(1)
    end
    
    function draw()
        background(0)
        if t1:test() then
            print(".3   ",t1.s:gettime())
        end
        if t2:test() then
            print(".5   ",t2.s:gettime())
        end
        if t3:test() then
            print("1.0  ",t3.s:gettime())
        end
    end
    
    checkDelay=class()
    
    function checkDelay:init(int)
        self.s=require("socket")
        self.start=self.s:gettime()
        self.val=0
        self.interval=int    
    end
    
    function checkDelay:test()
        if self.s:gettime()-self.start>self.val then
            self.val=self.val+self.interval
            return true
        end
        return false
    end
    
Sign In or Register to comment.