[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";