Re: pack

2002-02-21 Thread $Bill Luebkert

Sisyphus wrote:

> - Original Message -
> From: "Will W" <[EMAIL PROTECTED]>
> 
>>Everyone's fascination with sysread() got me to poking around in the
>>camel and cookbook a bit-- and I still can't see the advantage here of
>>doing a low-level system call over using read(), which is generally
>>buffered for optimal efficiency on whatever system your using. sysread()
>>makes a lot of sense on a port, but on a disk file I'm not seeing the
>>why of it-- maybe someone will enlighten me.
>>
>>
> 
> To have a closer look at 'read' versus 'sysread' I did a benchmark test.
> 
> I found that 'sysread' took (almost exactly) twice as long as 'read'.
> 
> So that was a pretty pertinent point you raised, Will.
> Guess I'd have to agree that I, too, don't see the advantage of using
> sysread in preference to read.
> 
> I also ran the same code using the trick with '$/' (which is also mentioned
> in perlvar, btw). Not surprisingly it's pretty much the same speed as
> 'read'.


sysread is unbuffered.  To get the same kind of results, you would need
to read a block of data and then feed the data 4 bytes at a time from a
subroutine that holds the buffered data and do another read when you run
out of data in that block.

-- 
   ,-/-  __  _  _ $Bill Luebkert   ICQ=14439852
  (_/   /  )// //   DBE Collectibles   Mailto:[EMAIL PROTECTED]
   / ) /--<  o // //  http://dbecoll.tripod.com/ (Free site for Perl)
-/-' /___/_<_http://www.todbe.com/

___
Perl-Win32-Users mailing list
[EMAIL PROTECTED]
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs



Re: pack

2002-02-21 Thread Sisyphus


- Original Message -
From: "Will W" <[EMAIL PROTECTED]>

>
> Everyone's fascination with sysread() got me to poking around in the
> camel and cookbook a bit-- and I still can't see the advantage here of
> doing a low-level system call over using read(), which is generally
> buffered for optimal efficiency on whatever system your using. sysread()
> makes a lot of sense on a port, but on a disk file I'm not seeing the
> why of it-- maybe someone will enlighten me.
>

To have a closer look at 'read' versus 'sysread' I did a benchmark test.

I found that 'sysread' took (almost exactly) twice as long as 'read'.

So that was a pretty pertinent point you raised, Will.
Guess I'd have to agree that I, too, don't see the advantage of using
sysread in preference to read.

I also ran the same code using the trick with '$/' (which is also mentioned
in perlvar, btw). Not surprisingly it's pretty much the same speed as
'read'.

Here's a cut'n'paste of both the code I ran and the result I got. Sorry if
it gets wrapped inconveniently.

use Benchmark;

timethese (1, {

'sysread' => 'open (READ, "d:/pscrpt/tab.new")
 or die "Cannot open READ: $!";
binmode READ;

while (sysread(READ, $read, 4) == 4) {
 $mod = unpack("I", $read);
 }

print "$mod\n";

close (READ) or die "Cannot close READ: $!";',


'read' => 'open (READ, "d:/pscrpt/tab.new")
 or die "Cannot open READ: $!";
binmode READ;

while (read(READ, $read, 4) == 4) {
 $mod = unpack("I", $read);
 }
print "$mod\n";

close (READ) or die "Cannot close READ: $!";',

'local' => '{
 local $/;
 $/ = \4;
open (READ, "d:/pscrpt/tab.new")
 or die "Cannot open READ: $!";
binmode READ;

while () {
 $mod = unpack("I", $_);
 }
print "$mod\n";

close (READ) or die "Cannot close READ: $!";
}',
});

##

Benchmark: timing 1 iterations of local, read, sysread...
27112421
 local: 25 wallclock secs (24.90 usr +  0.09 sys = 24.98 CPU) @  0.04/s
 (n=1)
(warning: too few iterations for a reliable count)
27112421
  read: 26 wallclock secs (26.42 usr +  0.10 sys = 26.52 CPU) @  0.04/s
 (n=1)
(warning: too few iterations for a reliable count)
27112421
   sysread: 53 wallclock secs (34.20 usr + 17.39 sys = 51.59 CPU) @  0.02/s
 (n=1)
(warning: too few iterations for a reliable count)

Cheers,
Rob

___
Perl-Win32-Users mailing list
[EMAIL PROTECTED]
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs



Re: pack

2002-02-21 Thread Will W


Hi, Carl--

Using the input record separator for fixed length records does work,
just as the the fine manual says. However I left out one critical
character in the code I sent last night-- the magic happens when $/ is
assigned a _reference_ to an integer value, as below.

use strict;
{
local $/;
   $/ = \4; # must be reference
   open IN, "test.dbx" or die "bad open: $!\n";
   binmode IN;
   my $i = 0;
   my $n = 0;
   while() {
  $n = unpack("I", $_);
  printf "%02d. %08X\n", $., $n;
  $i++;
  last if $i > 10;
   }
   close IN;
}

This behavior is documented in Wall, et al: _Programming perl, third
ed_, pg 666 (so I guess its sort of black magic). The above bit also
shows that $. does work in this mode.

--Will



Carl Jolley wrote on Thursday, February 21, 2002 1:35 PM
Subject: Re: pack


> On Thu, 21 Feb 2002, Will W wrote:
>
> > Sisyphus wrote on Wednesday, February 20, 2002 5:16 PM
> > Subject: Re: pack
> >
> >
> > > Thanks Will . now for a replacement for '$.' ?? :-))
> > > (Of course it's dead easy to craft one's own incremental counter.)
> > 
> > > > > while (1) {
> > > > > sysread(READ, $ret, 4);
> > 
> >
> > Everyone's fascination with sysread() got me to poking around in the
> > camel and cookbook a bit-- and I still can't see the advantage here
of
> > doing a low-level system call over using read(), which is generally
> > buffered for optimal efficiency on whatever system your using.
sysread()
> > makes a lot of sense on a port, but on a disk file I'm not seeing
the
> > why of it-- maybe someone will enlighten me.
> >
> > Anyway while poking around I ran yet another way to do the job which
> > really looks kind of interesting:
> >
> > [untested-- too much chianti on board to try it tonight]
> >
> > open IN, $somefile or die "gasp! $somefile! Uh! $!\n";
> > binmode IN;
> > { # closure for local
> > local $/;
> > $/ = 4; # see the camel
> > while () { # Should work, but wait there's more
> > $n = unpack("I", $_); # may have mangled the syntax
> > $line = $.;# Yep, you get this too!
> > } # endwhile
> > } # end localizing closure
> >
> > Now its time for bed. Spent the day developing a single subroutine
I'm
> > calling recurse_the_kids because its so dang descriptive of my
feelings
> > about its convolutions. And I'm out of chianti anyway.
> >
>
> By doing a: $/ = 4; all you've done is to set the input record
seperator
> character to a character "4". That will mean that if your file
contained
> the characters 0123456789 that doing a <> on that file would result
> in two records being read. The first one would contain 01234 and the
> second (and last) one would contain 56789. By default, $/ is the
> new-line character. Changing it tells perl that a different character
> should be used to separate records. If you set $/ to undefined, then
> the first <> operation on the filehandle will read all the characters
> it contains. Setting $/ has no effect if you are using read() or
> sysread() to access the data since those function read a specified
> number of characters not a record.
>
>
>  [EMAIL PROTECTED] 
>  All opinions are my own and not necessarily those of my employer

> k
>

___
Perl-Win32-Users mailing list
[EMAIL PROTECTED]
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs



Re: pack

2002-02-20 Thread Torsten Förtsch

On Thu, 21 Feb 2002 01:11:01 +1100
"Sisyphus" <[EMAIL PROTECTED]> wrote:

> Hi,
> 
> Ok - so I'm running the code below and it's working as I want - unless
> either of the 2 values being written to the file is 10. (ie unless $num = 8
> or 10).
> 
> If the value is 10, then I get a couple of warnings about 'use of
> uninitialised value'.
> '10' is the only value I've found that exhibits this disgraceful behaviour.
> 
> U .. I'm a little hard pressed to make sense of that 
> something to do with the newline characters or the chomping perhaps ?
> 
> use warnings;
> my $file = "try";
> my $num = 2;
> open (WRITEB, ">$file")
> or die "Can't open WRITEB: $!";
> binmode WRITEB;
> print WRITEB pack("I",$num,), "\n";

if $num==10 you are really printing "\n\0\0\0\n" to the file on a little
endian machine like a PC. pack( "I", 10 ) gives "\n\0\0\0". The least
significant byte is 10 which is the ASCII newline character.

> print WRITEB pack("I",$num + 2), "\n";
> close (WRITEB)
>  or die "Can't close WRITEB: $!";
> 
> open (READ, "$file")
> or die "Can't open READ: $!";
> binmode READ;
> while () {

Here you want to read one line at a time. If $num was 10 you will get 2
lines. The first one will be "\n" the 2nd "\0\0\0\n".

> chomp;

chomp makes "" from "\n".

> $ret = unpack("I", $_);

unpack( "I", "" ) yields undef.

> print $ret, "\n";

and here you get your warning

> }
> close (READ)
>  or die "Can't close READ: $!";
> 

In generally do not mix binary and line oriented IO. In your example you
can 
  print WRITEB pack("I",$num,);
without the newline and then use read or sysread:
  read READ, $_, length( pack( "I", 0 ) );

> Cheers,
> Rob
> 
> 
> ___
> Perl-Win32-Users mailing list
> [EMAIL PROTECTED]
> To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
> 
___
Perl-Win32-Users mailing list
[EMAIL PROTECTED]
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs



RE: pack

2002-02-20 Thread Joe Schell



> -Original Message-
> Behalf Of Morse, Richard E.
>
> Hah!  I know what the problem is!
>
> ASCII character 10 happens to be either \n -- so when you print
> this number to
> the file, you get a newline character for one of the bytes, so your
> while() loop finds three lines in the file instead of two.
>
> I think that in order to read this number back out of the file,
> you'll have to
> use sysread, instead of ...
>

In addition to the above you might want to look at why you would want a '\n'
in the file at all.  That is useful in a human readable file, but the file
you will end up with will not be readable.  And if you are looking for an
end of data marker I don't think a single character (or two for win32) is
going to be sufficient.  Either 0x or 0x are probably better choices
(or the 4 byte versions of each.)

>
> -Original Message-
> From: Sisyphus [mailto:[EMAIL PROTECTED]]
>
> Hi,
>
> Ok - so I'm running the code below and it's working as I want - unless
> either of the 2 values being written to the file is 10. (ie
> unless $num = 8
> or 10).
>
> If the value is 10, then I get a couple of warnings about 'use of
> uninitialised value'.
> '10' is the only value I've found that exhibits this disgraceful
> behaviour.
>
> U .. I'm a little hard pressed to make sense of that 
> something to do with the newline characters or the chomping perhaps ?
>
> use warnings;
> my $file = "try";
> my $num = 2;
> open (WRITEB, ">$file")
> or die "Can't open WRITEB: $!";
> binmode WRITEB;
> print WRITEB pack("I",$num,), "\n";
> print WRITEB pack("I",$num + 2), "\n";
> close (WRITEB)
>  or die "Can't close WRITEB: $!";
>
> open (READ, "$file")
> or die "Can't open READ: $!";
> binmode READ;
> while () {
> chomp;
> $ret = unpack("I", $_);
> print $ret, "\n";
> }
> close (READ)
>  or die "Can't close READ: $!";
>

___
Perl-Win32-Users mailing list
[EMAIL PROTECTED]
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs



RE: pack

2002-02-20 Thread Morse, Richard E.

Hah!  I know what the problem is!

ASCII character 10 happens to be either \n -- so when you print this number to
the file, you get a newline character for one of the bytes, so your
while() loop finds three lines in the file instead of two.

I think that in order to read this number back out of the file, you'll have to
use sysread, instead of ...

HTH,
Ricky

-Original Message-
From: Sisyphus [mailto:[EMAIL PROTECTED]]
Sent: Wednesday 20 February 2002 9:11 AM
To: [EMAIL PROTECTED]
Subject: pack 


Hi,

Ok - so I'm running the code below and it's working as I want - unless
either of the 2 values being written to the file is 10. (ie unless $num = 8
or 10).

If the value is 10, then I get a couple of warnings about 'use of
uninitialised value'.
'10' is the only value I've found that exhibits this disgraceful behaviour.

U .. I'm a little hard pressed to make sense of that 
something to do with the newline characters or the chomping perhaps ?

use warnings;
my $file = "try";
my $num = 2;
open (WRITEB, ">$file")
or die "Can't open WRITEB: $!";
binmode WRITEB;
print WRITEB pack("I",$num,), "\n";
print WRITEB pack("I",$num + 2), "\n";
close (WRITEB)
 or die "Can't close WRITEB: $!";

open (READ, "$file")
or die "Can't open READ: $!";
binmode READ;
while () {
chomp;
$ret = unpack("I", $_);
print $ret, "\n";
}
close (READ)
 or die "Can't close READ: $!";

Cheers,
Rob


___
Perl-Win32-Users mailing list
[EMAIL PROTECTED]
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
___
Perl-Win32-Users mailing list
[EMAIL PROTECTED]
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs