functional os.difftime() for LP 0.10?

Discuss using and improving Lua and the Lua Player specific to the PSP.

Moderators: Shine, Insert_witty_name

Post Reply
KawaGeo
Posts: 191
Joined: Sat Aug 27, 2005 6:52 am
Location: Calif Mountains

functional os.difftime() for LP 0.10?

Post by KawaGeo »

Here are two quotes regarding os.difftime() function:

From changes.txt in LP 0.10 package...
- os.time() returns a userdata instead of a number because of problems
with the float-precision, so you have to use os.difftime instead of
doing calculations with the result
and, from Lua 5.0 Reference...
os.difftime (t2, t1)

Returns the number of seconds from time t1 to time t2. In Posix, Windows, and
some other systems, this value is exactly t2-t1.
The code below is to test the functionality of the function in question for both LP-Win32 and LP 0.10...

Code: Select all

-- difftimetest.lua by Geo Massar, 2005 (aka KawaGeo)

green = Color.new(0,255,0)

local elapsedtime = 0
local t0 = os.clock()

repeat
  screen:clear()
  elapsedtime = os.difftime(os.clock() - t0)
  -- elapsedtime = os.clock() - t0
  screen:print(2,2, elapsedtime, green)
  screen.waitVblankStart()
  screen:flip()
until Controls.read():start()
The result is that it does not work on PSP with LP 0.10 but does on Windows, only seconds without fractional parts. However, without the function, it works on both platforms, showing in float format.

So, where is the beef? (says an old lady in TV ads if you are old enough to remember. :)
Geo Massar
Retired Engineer
Shine
Posts: 728
Joined: Fri Dec 03, 2004 12:10 pm
Location: Germany

Re: functional os.difftime() for LP 0.10?

Post by Shine »

KawaGeo wrote:

Code: Select all

  elapsedtime = os.difftime(os.clock() - t0)
Try os.difftime(os.clock(), t0).
KawaGeo
Posts: 191
Joined: Sat Aug 27, 2005 6:52 am
Location: Calif Mountains

Post by KawaGeo »

It does not work either way. I double checked with two different scripts to be sure.

Sorry, dude. The bug ate the beef!
Geo Massar
Retired Engineer
chaos
Posts: 135
Joined: Sun Apr 10, 2005 5:05 pm

Post by chaos »

i'm pretty sure i'm using this successfully in my game. it might have been os.time, i don't remember.. i'll check when i get done work.
Chaosmachine Studios: High Quality Homebrew.
Shine
Posts: 728
Joined: Fri Dec 03, 2004 12:10 pm
Location: Germany

Post by Shine »

Sorry, I mixed this up myself :-)

os.clock returns some number of seconds, which increments at least while the program is running (don't know when it will be resetted to 0, should be at program start, but looks like it doesn't). You can't use this for os.difftime(), this expects the result of os.time(), which could have a platform depenend meaning according to the Lua manual. So the right way to measure seconds is to use os.difftime with os.time values.
KawaGeo
Posts: 191
Joined: Sat Aug 27, 2005 6:52 am
Location: Calif Mountains

Post by KawaGeo »

I mixed this up myself, too.

I overlooked the os.time() in your changes.txt. I guess I need a new pair of glasses for my aged eyes. :(

I preferred os.clock() over os.time() for accuracy. It is for my little program. I believe the clock on PSP is reset at midnight. I could be wrong.

After done with the little project, I'll post it.

Thanks for your attention, Shine.
Geo Massar
Retired Engineer
Shine
Posts: 728
Joined: Fri Dec 03, 2004 12:10 pm
Location: Germany

Post by Shine »

I think a good idea would be a new Lua Player object, because os.difftime() can be used for seconds but os.clock() could be not exact enough, depending on the current value. Proposed interface:

t = MillisecondsTimer.new([startTime]) -> creates a new Timer object, reseted to 0 or startTime in milliseconds, if specified

t:time() -> milliseconds since creation of the timer object as a number

t:reset() -> resets the timer to 0

MillisecondsTimer.wait(number) -> pauses program execution for the specified time in milliseconds
KawaGeo
Posts: 191
Joined: Sat Aug 27, 2005 6:52 am
Location: Calif Mountains

Post by KawaGeo »

Shine,

Your proposal is terrific! May I suggest some alterations?

!. Use shorter Timer as a LP object rather than long name. Like other objects: Image, Color, etc. (I know Germans love long words. :)

2. Use Timer.pause(). "wait" sounds like waiting for something and "pause" like pause for a moment.

I just finished my "little" project named LED Timer. I used os.clock() for timing. The timing is pretty accurate. I will PM you where to find the zip file for your review. See if your proposal would "improve" my coding.

I am not ready to post the project however. I want to write a mini tutorial for young coders to learn about coding techniques.

Thanks.
Geo Massar
Retired Engineer
Shine
Posts: 728
Joined: Fri Dec 03, 2004 12:10 pm
Location: Germany

Post by Shine »

Ok, "Timer" is better, the documentation says already that it is a millisecond timer, no need to type it yourself everytime :-)
And you are right, "wait" sounds like waiting for some event, but "pause" is unusal, what do you think about "sleep"? This is the same like in Java and nearly the same in Unix (sleeping seconds instead of milliseconds).

Your LED Timer looks nice, I think this should be integrated as a demo application with the standard distribution, if you like and when it is ready. This will be a good demonstration for the new Timer class and it will be more exact, because currently it looks like sometimes some 1/10th seconds are missed displaying.
KawaGeo
Posts: 191
Joined: Sat Aug 27, 2005 6:52 am
Location: Calif Mountains

Post by KawaGeo »

I like "sleep" better. I have seen this word in other languages. Again, may I suggest some modifications and some additional features.

The new features are start() and hold() commands. Here is the revised proposal below. Please compare it to Shine's original proposal in this thread.

Thanks.

Revised proposal:

t = Timer.new([startTime])
-> creates a new Timer object, sets to 0 or startTime in milliseconds, if specified BUT don't start ticking as yet.

t:start()
-> starts to tick the timer, or resumes to tick after being held

t:time()
-> returns in milliseconds since the timer started/resumed

t:hold([number])
-> holds the timer for the specified time in milliseconds OR, in the absence of number, holds indefinitely until the timer starts again

t:reset([startTime])
-> resets the timer to 0 by default or startTime in milliseconds and holds

Timer.sleep(number)
-> pauses program execution for the specified time in milliseconds. It applies to ALL created timers as well.

The reason why t:start() command is important:

1. No need to recreate a timer.
2. The same timer can start again after being reset.

As for t:hold() command:

1. It would help to profile the bottleneck with a timer, if there is such one.
2. Any other reasons? (My mind is already numbed. <sigh>)
Last edited by KawaGeo on Tue Sep 27, 2005 11:48 am, edited 1 time in total.
Geo Massar
Retired Engineer
KawaGeo
Posts: 191
Joined: Sat Aug 27, 2005 6:52 am
Location: Calif Mountains

Post by KawaGeo »

Your LED Timer looks nice, I think this should be integrated as a demo application with the standard distribution, if you like and when it is ready. This will be a good demonstration for the new Timer class and it will be more exact, because currently it looks like sometimes some 1/10th seconds are missed displaying.
LED Timer is meant to be a model for tutorial purpose. It is being only in an early phase. The next phase will be more suitable for your future distribution with new version. This phase will be considered a homework assignment for those young coders. After done with the assignment, the new LED Timer will be ready to go.

Anyway, thank you for your consideration.
Geo Massar
Retired Engineer
KawaGeo
Posts: 191
Joined: Sat Aug 27, 2005 6:52 am
Location: Calif Mountains

Post by KawaGeo »

... currently it looks like sometimes some 1/10th seconds are missed displaying.
In order to know how fast the frame rate is on PSP, I wrote a short program called FPS Tester using the same displayDial() function. You can find it at my webpage.

Tested FPS on Windows. The range was from 28 to 48 fps depending how much tasks are running background. Fast enough for LED Timer. But on PSP, it was only 8 fps. I was shocked. That explained why some tenths were missing. Ideal rate should be at least 10 fps on PSP.

It might be due to too much blitting.

I wonder:

1. Why created images (the same size as the screen) can not be flipped? It has to be the screen per se.

2. Why does screen:caption() or any other user-defined functions like those in LPut.lua by using screen as the object not work?

With the changes, the frame rate would be speeded up, would it?

Thanks.
Geo Massar
Retired Engineer
KawaGeo
Posts: 191
Joined: Sat Aug 27, 2005 6:52 am
Location: Calif Mountains

Post by KawaGeo »

Great news. Blitting wasn't at fault. I found out how to speed up FPS rate to max. It was from 8 fps zooming to 60 on PSP! No more tenths missing. I am sending the new version via PM. It is ready to release.
Geo Massar
Retired Engineer
Shine
Posts: 728
Joined: Fri Dec 03, 2004 12:10 pm
Location: Germany

Post by Shine »

KawaGeo wrote:Revised proposal:

t = Timer.new([startTime])
-> creates a new Timer object, sets to 0 or startTime in milliseconds, if specified BUT don't start ticking as yet.

t:start()
-> starts to tick the timer, or resumes to tick after being held

t:time()
-> returns in milliseconds since the timer started/resumed

t:hold([number])
-> holds the timer for the specified time in milliseconds OR, in the absence of number, holds indefinitely until the timer starts again

t:reset([startTime])
-> resets the timer to 0 by default or startTime in milliseconds and holds

Timer.sleep(number)
-> pauses program execution for the specified time in milliseconds. It applies to ALL created timers as well.
The inially stopped timer and the start and reset function definitions makes sense and it is more similiar to a stopwatch and makes it easier to use it for some cases. But I don't see any reason for the hold function with a predefined time (and without a possible optional parameter, it should be called "stop").
KawaGeo
Posts: 191
Joined: Sat Aug 27, 2005 6:52 am
Location: Calif Mountains

Post by KawaGeo »

You are right. "Stop" is more familiar to stopwatch users. A stopped watch can be resumed without being reset. One wants to measure time during a specific event, not others. A race car driver stops at his pit for changing tires and resumes to finish the race, for instance.

Make sense?
Geo Massar
Retired Engineer
KawaGeo
Posts: 191
Joined: Sat Aug 27, 2005 6:52 am
Location: Calif Mountains

Post by KawaGeo »

Another instance:

In the game loop, mark events with "start and stop flags" for each event. Measure time for each event during the game loop. At the end of game loop, save those records on a file. Upon reading the file, you would be able to spot a bottleneck.

More sense?
Geo Massar
Retired Engineer
Shine
Posts: 728
Joined: Fri Dec 03, 2004 12:10 pm
Location: Germany

Post by Shine »

[quote="KawaGeo"]In the game loop, mark events with "start and stop flags" for each event. Measure time for each event during the game loop. At the end of game loop, save those records on a file. Upon reading the file, you would be able to spot a bottleneck.
[quote]

I don't understand what you mean. You want to measure some tasks, like drawing a picture. This would be t=Timer.new(); t.start(); longTask; t.timer() and then t.timer.reset(); t.start(); nextLongTask; etc.

Revised proposal. Note the minor changes: I don't think it is very useful to sleep all timers while sleeping the program execution and I've added some return values:

t = Timer.new([startTime])
-> creates a new Timer object, sets to 0 or startTime in milliseconds, if specified BUT don't start ticking as yet.

t:start()
-> starts to tick the timer, or resumes to tick after being stopped. Returns the current time() value. If the timer is running, it is the same as time()

t:time()
-> returns in milliseconds since the timer started/resumed

t:stop()
-> stops the timer. Returns the current time(). Subsequent time() calls returns the value when stopped. If the timer is stopped, this call is the same as time()

t:reset([startTime])
-> resets the timer to 0 by default or startTime in milliseconds and holds. Returns the time before resetted to the new value.

Timer.sleep(number)
-> pauses program execution for the specified time in milliseconds. It doesn't affect any timer object.
KawaGeo
Posts: 191
Joined: Sat Aug 27, 2005 6:52 am
Location: Calif Mountains

Post by KawaGeo »

Ok.

Let say taskA which draws a pickure and taskB, draws another picture. Create timers by calling Timer.new() before the game loop starts. In the game loop, at start of taskA, execute taskA:start() and at the end of taskA, taskA:stop(). Same for taskB at other place in the loop. Keep going on in the loop. Tasks accumulate timing during the looping. The table below best illustrates:

Code: Select all

        taskA  taskB
loop 1&#58;   21     3     during the first loop
loop 2&#58;   40     5     during the second loop
loop 3&#58;   59     9        etc.
loop 4&#58;   79    12
  ...
loop n&#58; 2055   566     the last loop before exiting 
&#40;all in milliseconds&#41;
Record the results using taskA:time() and taskB:time() on a file. From the reading, it is clear that taskA takes much longer than taskB. Hence, the culprit slows down the FPS rate. Recall: at 60 fps, the timing of the loop must be less than 17ms to keep the running at the max rate. In the table at n=100 loops, the ave for taskA is 20.55ms, too long. The slow taskA need be fixed if possible.

Not just two tasks but many more as suspects in the game loop in order to locate a bottleneck.

This is just one of many possibilities with Timer functions.

I like the second revision. Most functions return current values which might be useful in some cases.

I have one last but not the least question:

How can the timers keep running whenever the program pauses by calling Timer.sleep()? What is the purpose of keeping the timers running in spite of the program being paused for a moment or so?

In my mind, whenever the clock on the wall stops, everybody in the room must stop moving like the happening in TV ads.

When a cop says freeze, you better freeze. :)
Geo Massar
Retired Engineer
Shine
Posts: 728
Joined: Fri Dec 03, 2004 12:10 pm
Location: Germany

Post by Shine »

KawaGeo wrote:I have one last but not the least question:

How can the timers keep running whenever the program pauses by calling Timer.sleep()? What is the purpose of keeping the timers running in spite of the program being paused for a moment or so?

In my mind, whenever the clock on the wall stops, everybody in the room must stop moving like the happening in TV ads.

When a cop says freeze, you better freeze. :)
One answer is, that you can't measure task runtime otherwise. If a task calls a Timer.sleep(), at the end you don't know how long the task really needed. But for me it is obvious: When I sleep, clocks keep running :-)
But perhaps the sleep function should be in the system class (System.sleep(123)) to avoid confusions.
KawaGeo
Posts: 191
Joined: Sat Aug 27, 2005 6:52 am
Location: Calif Mountains

Post by KawaGeo »

Yes, I'd prefer System.sleep(milliseconds) likr any other languages.

From the example earlier in this thread, when taskB calls System.sleep(x), its timer is still running while taskA's timer isn't because it called to stop running previously in the loop.

Agreeable?
Geo Massar
Retired Engineer
Post Reply