[Perl] FileHandles en Windows....

Alejandro G. Bedoya nezumi@prodigy.net.mx
Tue, 02 Apr 2002 12:29:42 -0600


Saludos!!!

    Tengo una rutina que me abre archivos NDB, que son simplemente ar=
chivos
planos haciendose pasar como tablas, que tienen una estructura as=
=ED:

NID|KEYCARD|TIMESTAMP|EVENTCODE
2|114|1005228840|14
4|18|1005228900|14
5|151|1005228960|16
6|159|1005229020|14
7|151|1005229020|14
=2E......

    La primera l=EDnea es el nombre del campo y todas las demas son s=
us
registros, todo separado por pipes, y si el archivo tiene un campo ll=
amado
NID, se crea la llave sobre ese sino lo hace secuencial al momento. L=
o que
hace la rutina GETNDBFILE1, es abrir el archivo y sobre su contenido =
hacer
un hash de hashes con todos los datos. As=ED rapidamente puedo abrir =
cualquier
archivo NDB y accesar a sus datos simplemente:

my %Datos=3D&GETNDBFILE1("transaction.ndb");
print $Datos{'6'}{'TIMESTAMP'};  #Da 1005229020

    Esto me ha funcionando bastante bien, y en muchas ocasiones abro =
muchas
tablas NDB seguidas para ver sus datos y ya sobre eso procesarlas:

my %Usuarios=3D&GETNDBFILE1("usuarios.ndb");
my %Ordenes=3D&GETNDBFILE1("ordenes.ndb");
my %Proveedores=3D&GETNDBFILE1("proveedores.ndb");
=2E....

    Aparentemente sin ningun problema esto ha funcionado, pero recien=
temente
con tablas "grandes" me di cuenta que cada vez que abria una tabla se=
guida,
se tardaba mucho m=E1s independientemente del nombre de la variabla y=
/o
archivo. Crei que era un leek de algun tipo con mis variables con la
funci=F3n, pero como soy muy estricto con mis variables siempre uso U=
SE
STRICT, descartando eso inmediatamente. Hice un programita sencillo, =
para
probar la velocidad... en Windows me da esto:

=3D=3D>Leyendo ACCESOS1, 61521 registros en 8 segundos.
=3D=3D>Leyendo ACCESOS2, 61521 registros en 749 segundos.
=3D=3D>Leyendo ACCESOS3, 61521 registros en 1426 segundos.

En Linux, el mismo programa con el mismo archivo NDB, me da esto:

=3D=3D>Leyendo ACCESOS1, 61521 registros en 4 segundos.
=3D=3D>Leyendo ACCESOS2, 61521 registros en 4 segundos.
=3D=3D>Leyendo ACCESOS3, 61521 registros en 4 segundos.

#Nota al margen: Mi m=E1quina Windows es una Pentium III a un 1ghz. c=
on 254 mb
de #ram. La Linux es una Celeron a 700mhz con 192mb de ram... Otra ra=
z=F3n
para #mejorar..

Usando el debugger universal:  print "Hasta aqui voy...",  llegue a l=
a
conclusi=F3n que el problema esta en la funci=F3n extactamente en la =
linea:

        my @FileData =3D <FileHandle>;

    S=ED, ya se que Salvador recomienda abrir todo directamente para
procesarlo y no meterlo en la memoria, pero independientemente de eso
deberia de funcionar. Al parecer el problema esta que en mi versi=
=F3n de PERL
para Windows, los FileHandles globales si se los toma demasiado en se=
rio...
El PERL -v me muestra:
This is perl, v5.6.1 built for MSWin32-x86-multi-thread
(with 1 registered patch, see perl -V for more detail)

Copyright 1987-2001, Larry Wall

Binary build 626 provided by IndigoSTAR Software. http://www.indigost=
ar.com
Built 21:37:25 May  6 2001

Las preguntas:
1.- Alguien tiene este problema con el ActivePerl o similar de Window=
s???

2.- Esta bien mi proceso de abrir, lockear y cerrar el archivo???

3.- Estoy lockeando bien el archivo??? IndigoPerl no lo permite, por =
eso el
if, sin embargo en una tabla peque=F1a que tiene muchos accesos, siem=
pre se
corrompe estando en Linux.

4.- Cuando deberia de morir el FileHandle??? No se supone que es con =
el
close??


Aqui est=E1 todo el c=F3digo del programa prueba:


use strict;

sub GETNDBFILE1 {
 my $FID;
 my %DATA=3D();
 open(FileHandle,$_[0]) || die "$_[0]: $!";
 if ($^O ne "MSWin32") { flock(FileHandle, 2); }
 my @FileData =3D <FileHandle>;   #Aqui esta la bronca...
 close(FileHandle);
 chomp(@FileData);
 my @Fields =3D split(/\|/, shift @FileData);
 if ($Fields[0] eq "NID") {
  shift @Fields;
  $FID=3D0;
  } else {
  $FID=3D1;
  }
 foreach my $FileLine (@FileData) {
  my $Counter=3D0;
  my (@Datas) =3D split(/\|/, $FileLine);
  foreach my $Field (@Fields) {
   $Counter++;
   if ($FID>0) {
    $DATA{$FID}{$Field}=3D$Datas[$Counter-1];
    } else {
    $DATA{$Datas[0]}{$Field}=3D$Datas[$Counter];
    }
   }
  if ($FID>0) { $FID++; }
  }
 return %DATA;
 }

my $Start=3Dtime;
my $This=3D$Start;
my $Counter;

print "=3D=3D>Leyendo ACCESOS1, ";
$Counter=3D0;
$This=3Dtime;
my %Accesos1=3D&GETNDBFILE1("transaction.ndb");
$Counter=3D scalar keys %Accesos1;
$This=3Dtime-$This;
print "$Counter registros en $This segundos.\n";

print "=3D=3D>Leyendo ACCESOS2, ";
$Counter=3D0;
$This=3Dtime;
my %Accesos2=3D&GETNDBFILE1("transaction.ndb");
$Counter=3D scalar keys %Accesos2;
$This=3Dtime-$This;
print "$Counter registros en $This segundos.\n";

print "=3D=3D>Leyendo ACCESOS3, ";
$Counter=3D0;
$This=3Dtime;
my %Accesos3=3D&GETNDBFILE1("transaction.ndb");
$Counter=3D scalar keys %Accesos3;
$This=3Dtime-$This;
print "$Counter registros en $This segundos.\n";