Daniel McBrearty wrote:

> I wrote a script today that started a thread that was polling every
> 1000ms. I used
> 
> use Time::HiRes qw( usleep );
> usleep(1000 * 1000);
> 
> I didn't get the stopwatch out, but it looked as if the timing was way
> off. As I need to scale to much shorter timings, I need to use this
> module.
> 
> Does anyone else have this experience and know why it is so?

Works for me - the longer the time, the more accurate it should be since
timers don't have the same resolution that clocks do.  I think they're
accurate to 10-15 msec on Intel and use message passing which could affect
shorter times.  You can also use Win32::GetTickCount for a possibly more
accurate resolution (not a timer per se).  QueryPerformanceCounter /
QueryPerformanceFrequency can access an 8 usec counter if avail.  I have
some code after this snippet that you could try if you need to time a
chunk of code accurately - just call start_PC_timer before and stop_PC_timer
after.

Try this and see what you get (also try varying the time - I'm using
10 secs below):

use strict;
use warnings;
use Time::HiRes qw(usleep);

for (1 .. 10) {
        my $pt0 = Win32::GetTickCount ();
        usleep ($_ * 1000 * 1000);
        printf "%.3f seconds\n", (Win32::GetTickCount () - $pt0) / 1000;
}

__END__


#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

use strict;
use warnings;
use Win32::API;

my $QueryPerformanceCounter;            # API function obj once set in PC_init
my $QueryPerformanceFrequency;          # API function obj once set in PC_init
my $PC_Freq;                    # computed performance counter freq in seconds
my $QPC_Ovhd;                   # computed overhead of QPC API call in seconds

sub init_PC {           # set 4 global vrbls for using timing routines

return if $QueryPerformanceCounter;

$QueryPerformanceCounter = new Win32::API('kernel32',
  'QueryPerformanceCounter', [qw(P)], 'I') or die
  'Failed to get QueryPerformanceCounter:', Win32::FormatMessage (
  Win32::GetLastError ());                      # set global

$QueryPerformanceFrequency = new Win32::API('kernel32',
  'QueryPerformanceFrequency', [qw(P)], 'I') or die
  'Failed to get QueryPerformanceFrequency:', Win32::FormatMessage (
  Win32::GetLastError ());                      # set global

my $Freq = pack 'I2', 0;
if (not $QueryPerformanceFrequency->Call($Freq)) {
        die 'QueryPerformanceFrequency call failed:',
        Win32::FormatMessage (Win32::GetLastError ());
}

my @Freq = reverse unpack 'I2', $Freq;
$PC_Freq = $Freq[0] * 2**32 + $Freq[1]; # set global

printf "QueryPerformanceCounter freq: 1/%u sec\n\n", $PC_Freq if $debug;

$QPC_Ovhd = get_QPC_overhead ();                # set global

}

#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

sub get_QPC_overhead {

my $Ctr1 = pack 'I2', 0;
my $Ctr2 = pack 'I2', 0;
if (not $QueryPerformanceCounter->Call($Ctr1)) {
        die 'QueryPerformanceCounter call failed:',
        Win32::FormatMessage (Win32::GetLastError ());
}

my $max_loops = 100;            # adjust down to lower overhead
my $total = 0;
for (1 .. $max_loops) {

        $QueryPerformanceCounter->Call($Ctr1);
        $QueryPerformanceCounter->Call($Ctr2);

        my @Ctr1 = reverse unpack 'I2', $Ctr1;
        my @Ctr2 = reverse unpack 'I2', $Ctr2;

        printf "Start Value: %u, %u\n", $Ctr1[0], $Ctr1[1] if $debug;
        printf "End Value:   %u, %u\n", $Ctr2[0], $Ctr2[1] if $debug;

        my $diff = ($Ctr2[0] * 2**32 + $Ctr2[1]) -
          ($Ctr1[0] * 2**32 + $Ctr1[1]);
        printf "diff: %u / freq: %u = %f\n\n", $diff, $PC_Freq,
          $diff / $PC_Freq if $debug;
        $total += $diff;
}
my $ovhd = $total / $max_loops / $PC_Freq;
printf "API Overhead: %.8f seconds\n", $ovhd if $debug;
return $ovhd

}

#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

sub start_PC_timer {

init_PC ();
my $Ctr1 = pack 'I2', 0;
$QueryPerformanceCounter->Call($Ctr1);
my @Ctr1 = reverse unpack 'I2', $Ctr1;
return [EMAIL PROTECTED];

}

#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

sub stop_PC_timer {
        my $Ctr1ref = shift;

my $Ctr2 = pack 'I2', 0;
$QueryPerformanceCounter->Call($Ctr2);
my @Ctr2 = reverse unpack 'I2', $Ctr2;
my $diff = ($Ctr2[0] * 2**32 + $Ctr2[1]) - ($Ctr1ref->[0] * 2**32 +
  $Ctr1ref->[1]);
my $et = ($diff - $QPC_Ovhd) / $PC_Freq;
printf "Elapsed time: %f\n", $et if $debug;
return $et;

}

#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

_______________________________________________
Perl-Win32-Users mailing list
Perl-Win32-Users@listserv.ActiveState.com
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs

Reply via email to