cleaned up bench_spew_list to be more consistant in names and options
[urisagit/Perl-Docs.git] / extras / slurp_bench.pl
CommitLineData
635c7876 1#!/usr/local/bin/perl
2
3use strict ;
4use warnings ;
5
6use Getopt::Long ;
7use Benchmark qw( timethese cmpthese ) ;
8use Carp ;
9use FileHandle ;
10use Fcntl qw( :DEFAULT :seek );
11
12use File::Slurp () ;
13
14my $file = 'slurp_data' ;
8ff593f5 15my( @lines, $text ) ;
635c7876 16
fa575d4f 17my %opts ;
635c7876 18
19parse_options() ;
20
21run_benchmarks() ;
22
23unlink $file ;
24
25exit ;
26
635c7876 27sub run_benchmarks {
28
fa575d4f 29 foreach my $size ( @{$opts{size_list}} ) {
635c7876 30
fa575d4f 31 @lines = ( 'a' x 80 . "\n") x ( $size / 81 + 1 ) ;
635c7876 32 $text = join( '', @lines ) ;
fa575d4f 33
34 my $overage = length($text) - $size ;
35 substr( $text, -$overage, $overage, '' ) ;
36 substr( $lines[-1], -$overage, $overage, '' ) ;
635c7876 37
8ff593f5 38 if ( $opts{slurp} ) {
39
40 File::Slurp::write_file( $file, $text ) ;
41
42 bench_list_slurp( $size ) if $opts{list} ;
43 bench_scalar_slurp( $size ) if $opts{scalar} ;
44 }
635c7876 45
8ff593f5 46 if ( $opts{spew} ) {
47
48 bench_spew_list( $size ) if $opts{list} ;
49 bench_scalar_spew( $size ) if $opts{scalar} ;
50 }
635c7876 51 }
52}
53
54sub bench_spew_list {
55
8ff593f5 56 my( $size ) = @_ ;
635c7876 57
58 print "\n\nWriting (Spew) a list of lines: Size = $size bytes\n\n" ;
59
8ff593f5 60 my $result = timethese( $opts{iterations}, {
635c7876 61 'FS::write_file' =>
62 sub { File::Slurp::write_file( $file, @lines ) },
8ff593f5 63 'FS::write_file Aref' =>
64 sub { File::Slurp::write_file( $file, \@lines ) },
635c7876 65 'print' =>
66 sub { print_file( $file, @lines ) },
635c7876 67 'print/join' =>
68 sub { print_join_file( $file, @lines ) },
635c7876 69 'syswrite/join' =>
70 sub { syswrite_join_file( $file, @lines ) },
635c7876 71 'original write_file' =>
72 sub { orig_write_file( $file, @lines ) },
635c7876 73 } ) ;
74
75 cmpthese( $result ) ;
76}
77
8ff593f5 78sub print_file {
79
80 my( $file_name ) = shift ;
81
82 unlink $file_name ;
83
84 local( *FH ) ;
85 open( FH, ">$file_name" ) || carp "can't create $file_name $!" ;
86
87 print FH @_ ;
88}
89
90sub print_join_file {
91
92 my( $file_name ) = shift ;
93
94 unlink $file_name ;
95
96 local( *FH ) ;
97 open( FH, ">$file_name" ) || carp "can't create $file_name $!" ;
98
99 print FH join( '', @_ ) ;
100}
101
102sub syswrite_join_file {
103
104 my( $file_name ) = shift ;
105
106 unlink $file_name ;
107
108 local( *FH ) ;
109 open( FH, ">$file_name" ) || carp "can't create $file_name $!" ;
110
111 syswrite( FH, join( '', @_ ) ) ;
112}
113
114sub sysopen_syswrite_join_file {
115
116 my( $file_name ) = shift ;
117
118 unlink $file_name ;
119
120 local( *FH ) ;
121 sysopen( FH, $file_name, O_WRONLY | O_CREAT ) ||
122 carp "can't create $file_name $!" ;
123
124 syswrite( FH, join( '', @_ ) ) ;
125}
126
127sub orig_write_file
128{
129 my ($f, @data) = @_;
130
131 unlink $f ;
132
133 local(*F);
134
135 open(F, ">$f") || croak "open >$f: $!";
136 (print F @data) || croak "write $f: $!";
137 close(F) || croak "close $f: $!";
138 return 1;
139}
140
635c7876 141# sub bench_scalar_spew {
142
143# my ( $size ) = @_ ;
144
145# print "\n\nScalar Spew of $size file\n\n" ;
146
147# my $result = timethese( $dur, {
148
149# new =>
150# sub { File::Slurp::write_file( $file, $text ) },
151
152# new_ref =>
153# sub { File::Slurp::write_file( $file, \$text ) },
154
155# print_file =>
156# sub { print_file( $file, $text ) },
157
158# print_join_file =>
159# sub { print_join_file( $file, $text ) },
160
161# syswrite_file =>
162# sub { syswrite_file( $file, $text ) },
163
164# syswrite_file2 =>
165# sub { syswrite_file2( $file, $text ) },
166
167# orig_write_file =>
168# sub { orig_write_file( $file, $text ) },
169
170# } ) ;
171
172# cmpthese( $result ) ;
173# }
174
175# sub bench_scalar_slurp {
176
177# my ( $size ) = @_ ;
178
179# print "\n\nScalar Slurp of $size file\n\n" ;
180
181# my $buffer ;
182
183# my $result = timethese( $dur, {
184
185# new =>
186# sub { my $text = File::Slurp::read_file( $file ) },
187
188# new_buf_ref =>
189# sub { my $text ;
190# File::Slurp::read_file( $file, buf_ref => \$text ) },
191# new_buf_ref2 =>
192# sub {
193# File::Slurp::read_file( $file, buf_ref => \$buffer ) },
194# new_scalar_ref =>
195# sub { my $text =
196# File::Slurp::read_file( $file, scalar_ref => 1 ) },
197
198# read_file =>
199# sub { my $text = read_file( $file ) },
200
201# sysread_file =>
202# sub { my $text = sysread_file( $file ) },
203
204# orig_read_file =>
205# sub { my $text = orig_read_file( $file ) },
206
207# 'Slurp.pm scalar' =>
208# sub { my $text = slurp_scalar( $file ) },
209
210# file_contents =>
211# sub { my $text = file_contents( $file ) },
212
213# file_contents_no_OO =>
214# sub { my $text = file_contents_no_OO( $file ) },
215# } ) ;
216
217# cmpthese( $result ) ;
218# }
219
220# sub bench_list_slurp {
221
222# my ( $size ) = @_ ;
223
224# print "\n\nList Slurp of $size file\n\n" ;
225
226# my $result = timethese( $dur, {
227
228# new =>
229# sub { my @lines = File::Slurp::read_file( $file ) },
230
231# new_array_ref =>
232# sub { my $lines_ref =
233# File::Slurp::read_file( $file, array_ref => 1 ) },
234
235# new_in_anon_array =>
236# sub { my $lines_ref =
237# [ File::Slurp::read_file( $file ) ] },
238
239# read_file =>
240# sub { my @lines = read_file( $file ) },
241
242# sysread_file =>
243# sub { my @lines = sysread_file( $file ) },
244
245# orig_read_file =>
246# sub { my @lines = orig_read_file( $file ) },
247
248# 'Slurp.pm to array' =>
249# sub { my @lines = slurp_array( $file ) },
250
251# orig_slurp_to_array_ref =>
252# sub { my $lines_ref = orig_slurp_to_array( $file ) },
253# } ) ;
254
255# cmpthese( $result ) ;
256# }
257
258
259###########################
260# write file benchmark subs
261###########################
262
263
635c7876 264
265#######################
266# top level subs for script
267
268#######################
269
270sub parse_options {
271
fa575d4f 272 my $result = GetOptions (\%opts, qw(
273 iterations|i=s
274 direction|d=s
275 context|c=s
276 sizes|s=s
277 legend|key|l|k
278 help|usage
279 ) ) ;
280
281 usage() unless $result ;
282
283 usage() if $opts{help} ;
635c7876 284
fa575d4f 285 legend() if $opts{legend} ;
635c7876 286
fa575d4f 287# set defaults
635c7876 288
fa575d4f 289 $opts{direction} ||= 'both' ;
290 $opts{context} ||= 'both' ;
291 $opts{iterations} ||= -2 ;
292 $opts{sizes} ||= '500,10k,1m' ;
293
294 if ( $opts{direction} eq 'both' ) {
295
635c7876 296 $opts{spew} = 1 ;
297 $opts{slurp} = 1 ;
298 }
fa575d4f 299 elsif ( $opts{direction} eq 'in' ) {
635c7876 300
fa575d4f 301 $opts{slurp} = 1 ;
302
303 }
304 elsif ( $opts{direction} eq 'out' ) {
305
306 $opts{spew} = 1 ;
307 }
308 else {
309
310 usage( "Unknown direction: $opts{direction}" ) ;
311 }
635c7876 312
fa575d4f 313 if ( $opts{context} eq 'both' ) {
314
635c7876 315 $opts{list} = 1 ;
316 $opts{scalar} = 1 ;
317 }
fa575d4f 318 elsif ( $opts{context} eq 'scalar' ) {
635c7876 319
fa575d4f 320 $opts{scalar} = 1 ;
321
322 }
323 elsif ( $opts{context} eq 'list' ) {
635c7876 324
fa575d4f 325 $opts{list} = 1 ;
326 }
327 else {
328
329 usage( "Unknown context: $opts{context}" ) ;
330 }
331
332 if ( $opts{context} eq 'both' ) {
333
334 $opts{list} = 1 ;
335 $opts{scalar} = 1 ;
336 }
337 elsif ( $opts{context} eq 'scalar' ) {
635c7876 338
fa575d4f 339 $opts{scalar} = 1 ;
340
341 }
342 elsif ( $opts{context} eq 'list' ) {
343
344 $opts{list} = 1 ;
345 }
346 else {
347
348 usage( "Unknown context: $opts{context}" ) ;
349 }
350
351 foreach my $size ( split ',', ( $opts{sizes} ) ) {
352
353
354# check for valid size and suffix. grab both.
355
356 usage( "Illegal size: $size") unless $size =~ /^(\d+)([km])?$/ ;
635c7876 357
fa575d4f 358# handle suffix multipliers
635c7876 359
fa575d4f 360 $size = $1 * (( $2 eq 'k' ) ? 1024 : 1024*1024) if $2 ;
361
362 push( @{$opts{size_list}}, $size ) ;
363 }
364
365#use Data::Dumper ;
366#print Dumper \%opts ;
367}
368
369sub legend {
370
371 die <<'LEGEND' ;
8ff593f5 372Legend for the Slurp Benchmark Entries
635c7876 373
8ff593f5 374In all cases below 'FS' or 'F::S' means the current File::Slurp module
375is being used in the benchmark. The full name and description will say
376which options are being used.
635c7876 377
8ff593f5 378These benchmarks write a list of lines to a file. Use the direction option
379of 'out' or 'both' and the context option is 'list' or 'both'.
635c7876 380
381 Key Description/Source
382 --- ------------------
8ff593f5 383 FS::write_file Current F::S write_file
384 FS::write_file Aref Current F::S write_file on array ref of data
385 print Open a file and call print() on the list data
386 print/join Open a file and call print() on the joined
387 list data
388 syswrite/join Open a file, call syswrite on joined list data
389 sysopen/syswrite Sysopen a file, call syswrite on joined
390 list data
391 original write_file write_file code from original File::Slurp
392 (pre-version 9999.*)
635c7876 393
fa575d4f 394LEGEND
635c7876 395}
396
fa575d4f 397sub usage {
635c7876 398
fa575d4f 399 my( $err ) = @_ ;
635c7876 400
fa575d4f 401 $err ||= '' ;
635c7876 402
fa575d4f 403 die <<DIE ;
404$err
405Usage: $0 [--iterations=<iter>] [--direction=<dir>] [--context=<con>]
406 [--sizes=<size_list>] [--legend] [--help]
635c7876 407
fa575d4f 408 --iterations=<iter> Run the benchmarks this many iterations
409 -i=<iter> A positive number is iteration count,
410 a negative number is minimum CPU time in
411 seconds. Default is -2 (run for 2 CPU seconds).
635c7876 412
fa575d4f 413 --direction=<dir> Which direction to slurp: 'in', 'out' or 'both'.
414 -d=<dir> Default is 'both'.
635c7876 415
fa575d4f 416 --context=<con> Which context is used for slurping: 'list',
417 -c=<con> 'scalar' or 'both'. Default is 'both'.
635c7876 418
fa575d4f 419 --sizes=<size_list> What sizes will be used in slurping (either
420 -s=<size_list> direction). This is a comma separated list of
421 integers. You can use 'k' or 'm' as suffixes
422 for 1024 and 1024**2. Default is '500,1k,1m'.
635c7876 423
fa575d4f 424 --legend Print out a legend of all the benchmark entries.
425 --key
426 -l
427 -k
428
429 --help Print this help text
430 --usage
635c7876 431DIE
432
433}
434
635c7876 435__END__
436
437
438sub bench_scalar_spew {
439
440 my ( $size ) = @_ ;
441
442 print "\n\nScalar Spew of $size file\n\n" ;
443
444 my $result = timethese( $dur, {
445
446 new =>
447 sub { File::Slurp::write_file( $file, $text ) },
448
449 new_ref =>
450 sub { File::Slurp::write_file( $file, \$text ) },
451
452 print_file =>
453 sub { print_file( $file, $text ) },
454
455 print_join_file =>
456 sub { print_join_file( $file, $text ) },
457
458 syswrite_file =>
459 sub { syswrite_file( $file, $text ) },
460
461 syswrite_file2 =>
462 sub { syswrite_file2( $file, $text ) },
463
464 orig_write_file =>
465 sub { orig_write_file( $file, $text ) },
466
467 } ) ;
468
469 cmpthese( $result ) ;
470}
471
472sub bench_scalar_slurp {
473
474 my ( $size ) = @_ ;
475
476 print "\n\nScalar Slurp of $size file\n\n" ;
477
478 my $buffer ;
479
480 my $result = timethese( $dur, {
481
482 new =>
483 sub { my $text = File::Slurp::read_file( $file ) },
484
485 new_buf_ref =>
486 sub { my $text ;
487 File::Slurp::read_file( $file, buf_ref => \$text ) },
488 new_buf_ref2 =>
489 sub {
490 File::Slurp::read_file( $file, buf_ref => \$buffer ) },
491 new_scalar_ref =>
492 sub { my $text =
493 File::Slurp::read_file( $file, scalar_ref => 1 ) },
494
495 read_file =>
496 sub { my $text = read_file( $file ) },
497
498 sysread_file =>
499 sub { my $text = sysread_file( $file ) },
500
501 orig_read_file =>
502 sub { my $text = orig_read_file( $file ) },
503
504 orig_slurp =>
505 sub { my $text = orig_slurp_to_scalar( $file ) },
506
507 file_contents =>
508 sub { my $text = file_contents( $file ) },
509
510 file_contents_no_OO =>
511 sub { my $text = file_contents_no_OO( $file ) },
512 } ) ;
513
514 cmpthese( $result ) ;
515}
516
517sub bench_list_slurp {
518
519 my ( $size ) = @_ ;
520
521 print "\n\nList Slurp of $size file\n\n" ;
522
523 my $result = timethese( $dur, {
524
525 new =>
526 sub { my @lines = File::Slurp::read_file( $file ) },
527
528 new_array_ref =>
529 sub { my $lines_ref =
530 File::Slurp::read_file( $file, array_ref => 1 ) },
531
532 new_in_anon_array =>
533 sub { my $lines_ref =
534 [ File::Slurp::read_file( $file ) ] },
535
536 read_file =>
537 sub { my @lines = read_file( $file ) },
538
539 sysread_file =>
540 sub { my @lines = sysread_file( $file ) },
541
542 orig_read_file =>
543 sub { my @lines = orig_read_file( $file ) },
544
545 orig_slurp_to_array =>
546 sub { my @lines = orig_slurp_to_array( $file ) },
547
548 orig_slurp_to_array_ref =>
549 sub { my $lines_ref = orig_slurp_to_array( $file ) },
550 } ) ;
551
552 cmpthese( $result ) ;
553}
554
555######################################
556# uri's old fast slurp
557
558sub read_file {
559
560 my( $file_name ) = shift ;
561
562 local( *FH ) ;
563 open( FH, $file_name ) || carp "can't open $file_name $!" ;
564
565 return <FH> if wantarray ;
566
567 my $buf ;
568
569 read( FH, $buf, -s FH ) ;
570 return $buf ;
571}
572
573sub sysread_file {
574
575 my( $file_name ) = shift ;
576
577 local( *FH ) ;
578 open( FH, $file_name ) || carp "can't open $file_name $!" ;
579
580 return <FH> if wantarray ;
581
582 my $buf ;
583
584 sysread( FH, $buf, -s FH ) ;
585 return $buf ;
586}
587
588######################################
589# from File::Slurp.pm on cpan
590
591sub orig_read_file
592{
593 my ($file) = @_;
594
595 local($/) = wantarray ? $/ : undef;
596 local(*F);
597 my $r;
598 my (@r);
599
600 open(F, "<$file") || croak "open $file: $!";
601 @r = <F>;
602 close(F) || croak "close $file: $!";
603
604 return $r[0] unless wantarray;
605 return @r;
606}
607
608
609######################################
610# from Slurp.pm on cpan
611
612sub slurp {
613 local( $/, @ARGV ) = ( wantarray ? $/ : undef, @_ );
614 return <ARGV>;
615}
616
617sub slurp_array {
618 my @array = slurp( @_ );
619 return wantarray ? @array : \@array;
620}
621
622sub slurp_scalar {
623 my $scalar = slurp( @_ );
624 return $scalar;
625}
626
627######################################
628# very slow slurp code used by a client
629
630sub file_contents {
631 my $file = shift;
632 my $fh = new FileHandle $file or
633 warn("Util::file_contents:Can't open file $file"), return '';
634 return join '', <$fh>;
635}
636
637# same code but doesn't use FileHandle.pm
638
639sub file_contents_no_OO {
640 my $file = shift;
641
642 local( *FH ) ;
643 open( FH, $file ) || carp "can't open $file $!" ;
644
645 return join '', <FH>;
646}
647
648##########################