Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Why is using binmode on a file handle 77 times slower than just closing it and re-opening?

by Maelstrom (Sexton)
on Nov 25, 2024 at 04:46 UTC ( [id://11162873]=perlquestion: print w/replies, xml ) Need Help??

Maelstrom has asked for the wisdom of the Perl Monks concerning the following question:

One of the more questionable things my file reading modules does is keep a list of opened file handles in a global hash allowing me to perform multiple operations on a filehandle by name. I was benchmarking the write times for syswrite vs PerlIO and I found something very strange, while keeping the file handle open normally results in being an order of magnitude faster on the test where a binmode($fh,':encoding(UTF-8)) is used the rate drops from several thousand to 30 runs a second. It doesn't happen on read operations and it doesn't happen with just binmode($fh) (sans encoding). It's not a huge deal, just validates my decision to make not using PerlIO the default but still, 7700% is a lot of difference for what I would've assumed is the same basic operation. SSSCE and benchmark as follows...
use Benchmark qw/cmpthese timethese/; my (@array,%handle); my $file = 'testout.txt'; for (1 .. 1000) { push @array, 'It was the best of times, it was the w +orst of times...' . $/; } cmpthese(-8, { close => sub { &printfile(@array); }, noclose => sub { &printfile(@array,{noclose=>1}); }, }); sub printfile { my $opts = ( ref $_[-1] eq 'HASH' ) ? pop : {}; my $fh; my $string = join '', @_; if ($handle{$file}) { $fh = $handle{$file}; binmode $fh, ':encoding(UT +F-8)'; } else { open($fh, "> :encoding(UTF-8)", $file) || die "Can't open $file fo +r writing: $!"; $handle{$file} = $fh unless (! $opts->{'noclose'}); } seek($fh, 0, 0); print $fh $string; close $fh unless ($opts->{'noclose'}); }
Benchmark Results
          Rate noclose   close
noclose 29.9/s      --    -99%
close   2330/s   7705%      -- 
  • Comment on Why is using binmode on a file handle 77 times slower than just closing it and re-opening?
  • Select or Download Code

Replies are listed 'Best First'.
Re: Why is using binmode on a file handle 77 times slower than just closing it and re-opening?
by choroba (Cardinal) on Nov 25, 2024 at 08:41 UTC
    The problem is binmode doesn't change the layer of the filehandle, it adds a new layer.

    Try appending the following line to your test:

    warn PerlIO::get_layers($handle{$file});
    And then try to count how many times the string encoding(utf-8-strict)utf8repeats. In my case, it was 922 ×
    my @l = grep /utf-?8/, PerlIO::get_layers($handle{$file}); warn @l / 2;

    To fix that, clear the layers before applying new ones by starting with :raw:

    binmode $fh, ':raw:encoding(UTF-8)';
    The result becomes agreeable:
    Rate close noclose close 2137/s -- -28% noclose 2951/s 38% --
    And the warning now shows a pretty low number.

    Updated: Show how to count the repeated layers.

    Update 2: On MSWin, you might need to add :crlf after :raw if needed, too.

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
      Much thanks the universe makes sense again. The results got even better when I remembered to add the seek statement.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11162873]
Approved by Corion
Front-paged by choroba
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others lurking in the Monastery: (6)
As of 2024-12-12 16:54 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Which IDE have you been most impressed by?













    Results (65 votes). Check out past polls.