Have you tried read()? If the records are fixed length you could read in for a length * number rows and then split on the newline or read in a big chunk and add logic to keep a
partial record from the end of the buffer and add to it on the next read.
while ( read($fh, $buf, $len) ) {
@lines = split "\n", $buf;
.
.
.
}
It may be faster, worth a try.