пятница, 8 января 2016 г.

Особенности работы с файловыми дескрипторами в Perl

#!/usr/bin/perl 

use strict;
use warnings;

use Benchmark qw(:all);
use FileHandle;

cmpthese(100000, {
    fh_1 => sub {
        open my $fh1, "<", "a.txt" or die $!;
        my @whole_file = <$fh1>;
    },
    fh_2 => sub {
        open my $fh2, "<", "a.txt" or die $!;
        my @whole_file = $fh2->getlines;
    },
    fh_3 => sub {
        my $fh3 = FileHandle->new;
        $fh3->open("< a.txt") or die $!;
        my @whole_file = $fh3->getlines;
    }
});

__END__
        Rate fh_3 fh_2 fh_1
fh_3 29155/s   -- -36% -43%
fh_2 45872/s  57%   -- -11%
fh_1 51282/s  76%  12%   --


Во-первых, для того чтобы использовать объектные методы для файлового дескриптора (варианты fh_2, fh_3), необязательно прибегать к помощи модуля FileHandle, в чьей компетенции находится предоставление подобного функционала. Можно обойтись и без него, если прочитать пару строк из документации perlobj:

       Under the hood, Perl filehandles are instances of the "IO::Handle" or "IO::File" class. Once you have an open filehandle, you can call methods on it. Additionally, you can call methods on the "STDIN", "STDOUT", and "STDERR" filehandles.

         open my $fh, '>', 'path/to/file';
         $fh->autoflush();
         $fh->print('content');

         STDOUT->autoflush();

Т.е. как мы видим, под "капотом", файловые дескрипторы - это нечто иное, как экземпляры классов IO::Handle или IO::File.

Во-вторых, при Benchmark тестировании трёх вариантов реализации для чтения файла целиком (обычно так не делают конечно же), можно увидеть, что первенство остаётся за старым добрым "угловатым" способом для чтения файловых дескрипторов <$fh>.

Ну и в-третьих, вы уже, наверное, заметили, что в тестах не используется close для закрытия файловых дескрипторов, так как это выполняется автоматически самим Perl (perlopentut):

       Another convenient behavior is that an indirect filehandle automatically closes when there are no more references to it:

           sub firstline {
               open( my $in, shift ) && return scalar <$in>;
               # no close() required
           }

Комментариев нет:

Отправить комментарий