I can't seem to get values any finer than 40-60 milliseconds. I am using
Win98 SE if that matters...
Thanks for any hints or suggestions...
Jeff
% set tcl_patchLevel
8.4a4
for {set i 0} {$i < 50} {incr i} {
puts [clock click -milliseconds]
}
-999316302
-999316302
-999316302
-999316302
-999316302
-999316302
-999316302
-999316302
-999316242
-999316242
-999316242
-999316242
-999316242
-999316242
-999316242
-999316242
-999316242
-999316242
-999316192
-999316192
-999316192
-999316192
-999316192
-999316192
-999316192
-999316192
-999316192
-999316192
-999316192
-999316192
-999316132
-999316132
-999316132
-999316132
-999316132
-999316132
-999316132
-999316132
-999316132
-999316132
-999316132
-999316132
-999316082
-999316082
-999316082
-999316082
-999316082
-999316082
-999316082
-999316082
Unfortunatly, the changes were only for NT+. is uses the performance
counters that are part of that OS.
Tom Wilkason
That's not what I was hoping for, but thanks for the info...
Jeff
"Tom Wilkason" <tom.wi...@cox.net> wrote in message
news:uGan8.15119$DX6.3...@news2.east.cox.net...
That's not what I was hoping for, but thanks for the info...
Jeff
"Tom Wilkason" <tom.wi...@cox.net> wrote in message
news:uGan8.15119$DX6.3...@news2.east.cox.net...
--
73 de ke9tv/2, Kevin KENNY GE Corporate R&D, Niskayuna, New York, USA
OK, there are a couple of things that can cause this.
One is that you're running on a BIOS or a hardware abstraction layer that
doesn't support a performance counter (there are a few out there) or has a
frequency other than one of the 'standard' ones. Is the PC you're using
fairly conventional? The problem of weird performance counter
implementations comes up most often on server-class machines.
Another possibility is that you're actually producing 5-6 lines of console
output in less than a millisecond, and then your process loses control
while the OS flushes buffers to the console. We could see whether this
is the case by trying a timing study on something that won't block on
console I/O. Do you get the same sort of quantization if you run a
script like the following?
for { set i 1 } { $i < 1000000 } { set i [expr { $i * 10 }] } {
puts "$i: [time {
for { set j 0 } { $j < $i } { incr j } {}
}]"
}
If the latter script does show trouble, then I'm probably going to have
to work with you on trying some patches to diagnose the thing. Alas,
the behavior of the timing stuff on windows depends on both the OS and the
hardware, and so some of the testing would have to be done on your
machine.
Kevin,
Thanks for the response. You obviously know much more about this than I do.
All I really know is that is doesn't seem to work like I had expected. I'll
try your script when I get home and post the results. Regarding my machine,
it is fairly conventional:
PII 300
128 MB RAM
Win98SE
I would be more than happy to test anything you might suggest. If you have
other hardware related info, just ask and I'll pass it on.
Again, thanks for your help.
Jeff
"Kevin Kenny" <ken...@acm.org> wrote in message
news:3C9F529A...@acm.org...
Kevin,
Thanks for the response. You obviously know much more about this than I do.
All I really know is that is doesn't seem to work like I had expected. I'll
try your script when I get home and post the results. Regarding my machine,
it is fairly conventional:
PII 300
128 MB RAM
Win98SE
I would be more than happy to test anything you might suggest. If you have
other hardware related info, just ask and I'll pass it on.
Again, thanks for your help.
Jeff
"Kevin Kenny" <ken...@acm.org> wrote in message
news:3C9F529A...@acm.org...
For 1 millisecond granularity, use the windows beginTimePeriod()
and timeGetTime() calls from the winmm.lib/mmsystem.h library.
I do this all the time from C under 95, 98, 98SE, NT4, XP:
=========================== t.c:
#include <windows.h>
#include <mmsystem.h> // link against winmm.lib: cl t.c winmm.lib
int main(int argc, char **argv)
{
timeBeginPeriod(1);
printf("%d\n", timeGetTime());
Sleep(1234); // units are milliseconds
printf("%d\n", timeGetTime());
}
===========================
Run this and the numbers printed differ by 1234
or 1235 (the first printf latency is on top of the 1234 ms sleep)
So I tried the same calls from an extension, with TCL 8.4b2:
=========================== milliSecClock.c:
#include <tcl.h>
#include <windows.h>
#include <mmsystem.h> // link against winmm.lib
int milliSecClock (
ClientData clientData,
Tcl_Interp *interp,
int argc,
char *argv[]
)
{
sprintf(interp->result, "%d", timeGetTime());
return TCL_OK;
}
__declspec( dllexport )
int Millisecclock_Init (Tcl_Interp *interp)
{
if(!Tcl_InitStubs(interp, TCL_VERSION, 0)) {
sprintf(interp->result, "need TCL stubs %s or later",
TCL_VERSION);
return TCL_ERROR;
}
timeBeginPeriod(1);
Tcl_CreateCommand(interp, "milliSecClock", milliSecClock, 0, 0);
return TCL_OK;
}
=========================== milliSecClock.def:
LIBRARY milliSecClock.dll
EXPORTS
Millisecclock_Init
=========================== milliSecClock.mak:
!include <win32.MAK>
proj = milliSecClock
OBJ = milliSecClock.obj
mylibs = \progra~1\tcl\lib\tclstub84.lib winmm.lib
incs = -I /Progra~1/tcl/include
cflags = $(cflags) -W3 -O2
all: $(proj).dll
$(proj).dll: $(OBJ) $(proj).def
$(link) $(dlllflags) -out:$@ -def:$*.def $(guilibsdll) $(mylibs) $(OBJ)
milliSecClock.obj: milliSecClock.c milliSecClock.mak
$(cc) $(incs) $(cflags) $(cvarsdll) milliSecClock.c
===========================
Now from TCLSH84 or WISH84 "load milliSecClock.dll"
generates an access violation on the timeBeginTme() call!
Anyone have any idea why?
Having moved to 8.4b2, I no longer have any 8.3
installed so I have not tested it against any
of the 8.3 releases.
All of our other extensions run flawlessly
under 8.4b2 or any of the 8.4a+ series.
[some possible issues with original tests snipped...]
Do you get the same sort of quantization if you run a
> script like the following?
>
> for { set i 1 } { $i < 1000000 } { set i [expr { $i * 10 }] } {
> puts "$i: [time {
> for { set j 0 } { $j < $i } { incr j } {}
> }]"
> }
>
> If the latter script does show trouble, then I'm probably going to have
> to work with you on trying some patches to diagnose the thing. Alas,
> the behavior of the timing stuff on windows depends on both the OS and the
> hardware, and so some of the testing would have to be done on your
> machine.
Kevin,
Sorry, it took me a few days to run the timing tests you suggested. I don't
really understand enough about this to interpret the results, but they seem
*very* similar between 8.3 and 8.4 (both are included below). Ultimately, I
am trying to use [clock clicks -millseconds] to lock the frame rate on some
canvas animation to approx 30 frames/second (33 ms/frame). I want to do
this using something similar to the following:
while {$alive} {
get current millisecond time value (start_time)
update all components to represent the next frame
while {33 ms have not passed since start_time} {
do_nothing
}
[update] (draw the next frame)
}
The problem is that by the time I exit the [while] loop, it is either 50 or
60 ms past the start_time value. This effectively halves my frame rate
(knocks it down to approx 15 frames / second).
The following code shows my problem:
console show
set startTime [clock clicks -milliseconds]
set endTime [expr {$startTime + 33}]
#updateAllFrameComponents
set nowTime [clock clicks -milliseconds]
while {$nowTime < $endTime} {
set nowTime [clock clicks -milliseconds]
puts "Waiting: $startTime, $endTime, $nowTime"
}
puts "Done: $startTime, $endTime, $nowTime"
puts "Delta: [expr {$endTime - $nowTime}]"
Running this results in the following:
Waiting: -707921992, -707921959, -707921992
Waiting: -707921992, -707921959, -707921992
Waiting: -707921992, -707921959, -707921942
Done: -707921992, -707921959, -707921942
Delta: -17
Notice that $nowTime changes by 50 ms all at once (sometimes 60 ms). At
best, this changes my frame rate to 20 fps (1000/50) and sometimes 16.6 fps
(1000/60). I am trying to lock the frame rate to normalize the animation
speed of a game across varying hardware performance levels and going from an
expected frame rate of 30 fps to 16.6 fps *really* screws up the overall
feel.
Below are results of the test code you sent to me - running in both 8.4a4
and 8.3.2. Again, both seem to show similar results. Again, my system is
just a typical desktop, although maybe somewhat dated:
300 MHz PII
Win98 SE
128 MB RAM
I have tried the same tests on a newer system running Win98 with virtually
the same results (50-60 ms granularity):
500 MHz PIII
Win98 SE
64 MB RAM
Any assistance or suggestions would be *greatly* appreciated.
Thanks,
Jeff Godfrey
***** 8.4a4 below ******
(DESKTOP) 1 % set tcl_patchLevel
8.4a4
(DESKTOP) 3 % for { set i 1 } { $i < 1000000 } { set i [expr { $i * 10 }] }
{
> puts "$i: [time {
> for { set j 0 } { $j < $i } { incr j } {}
> }]"
> }
1: 0 microseconds per iteration
10: 0 microseconds per iteration
100: 0 microseconds per iteration
1000: 0 microseconds per iteration
10000: 110000 microseconds per iteration
100000: 1150000 microseconds per iteration
(DESKTOP) 4 % for { set i 1 } { $i < 1000000 } { set i [expr { $i * 10 }] }
{
puts "$i: [time {
for { set j 0 } { $j < $i } { incr j } {}
}]"
}
1: 0 microseconds per iteration
10: 0 microseconds per iteration
100: 0 microseconds per iteration
1000: 0 microseconds per iteration
10000: 110000 microseconds per iteration
100000: 1210000 microseconds per iteration
(DESKTOP) 5 % for { set i 1 } { $i < 1000000 } { set i [expr { $i * 10 }] }
{
puts "$i: [time {
for { set j 0 } { $j < $i } { incr j } {}
}]"
}
1: 0 microseconds per iteration
10: 0 microseconds per iteration
100: 0 microseconds per iteration
1000: 0 microseconds per iteration
10000: 110000 microseconds per iteration
100000: 1100000 microseconds per iteration
(DESKTOP) 6 % for { set i 1 } { $i < 1000000 } { set i [expr { $i * 10 }] }
{
puts "$i: [time {
for { set j 0 } { $j < $i } { incr j } {}
}]"
}
1: 0 microseconds per iteration
10: 0 microseconds per iteration
100: 0 microseconds per iteration
1000: 0 microseconds per iteration
10000: 110000 microseconds per iteration
100000: 1150000 microseconds per iteration
(DESKTOP) 7 %
***** 8.3.2 below ******
% set tcl_patchLevel
8.3.2
% for { set i 1 } { $i < 1000000 } { set i [expr { $i * 10 }] } {
> puts "$i: [time {
> for { set j 0 } { $j < $i } { incr j } {}
> }]"
> }
1: 0 microseconds per iteration
10: 0 microseconds per iteration
100: 0 microseconds per iteration
1000: 50000 microseconds per iteration
10000: 60000 microseconds per iteration
100000: 980000 microseconds per iteration
% for { set i 1 } { $i < 1000000 } { set i [expr { $i * 10 }] } {
puts "$i: [time {
for { set j 0 } { $j < $i } { incr j } {}
}]"
}
1: 0 microseconds per iteration
10: 0 microseconds per iteration
100: 0 microseconds per iteration
1000: 0 microseconds per iteration
10000: 50000 microseconds per iteration
100000: 990000 microseconds per iteration
% for { set i 1 } { $i < 1000000 } { set i [expr { $i * 10 }] } {
puts "$i: [time {
for { set j 0 } { $j < $i } { incr j } {}
}]"
}
1: 0 microseconds per iteration
10: 0 microseconds per iteration
100: 0 microseconds per iteration
1000: 0 microseconds per iteration
10000: 110000 microseconds per iteration
100000: 980000 microseconds per iteration
% for { set i 1 } { $i < 1000000 } { set i [expr { $i * 10 }] } {
puts "$i: [time {
for { set j 0 } { $j < $i } { incr j } {}
}]"
}
1: 0 microseconds per iteration
10: 0 microseconds per iteration
100: 0 microseconds per iteration
1000: 60000 microseconds per iteration
10000: 50000 microseconds per iteration
100000: 990000 microseconds per iteration
%
The code in tclWinTime.c seems to be tripping over something that's fairly
specific to Win98SE and possibly WinME. Could someone with access to those
platforms and a C compiler please tell me what the following program prints?
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
int
main( int argc, char* argv[] ) {
int iHavePerfCounter;
LARGE_INTEGER liPerfCounterFreq;
iHavePerfCounter = QueryPerformanceFrequency( &liPerfCounterFreq );
printf( "result = %d\nHighPart = 0x%08x and LowPart = 0x%08x\n",
iHavePerfCounter, liPerfCounterFreq.HighPart,
liPerfCounterFreq.LowPart );
return 0;
Rolf Ade was able to help me with some further tests. I've committed a change
that I think should fix the problem; can you try your tests against the current
HEAD?
Please note that Rolf Ade was able to try this test for me, and gave me the
information I need to fix the problem. Thanks, Rolf!