This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Clean: Actually use HvUSEDKEYS() instead of HvKEYS()
[perl5.git] / t / benchmark / rt26188-speed-up-keys-on-empty-hash.t
CommitLineData
58da6fbc
MM
1#!/usr/bin/perl -w
2use strict;
3use Benchmark;
4require './test.pl';
58da6fbc
MM
5plan(tests => 6);
6
7=head1 NAME
8
9rt26188 - benchmark speed for keys() on empty hashes
10
11=head1 DESCRIPTION
12
13If you have an empty hash, the speed of keys() depends
14on how many keys the hash previously held.
15
16For global hashes, getting the count for previously
17big hashes was substantially slower than for lexical hashes.
18
19This test checks that the speed difference for getting
20the number or list of keys from an empty hash is about the same
21(< 25%) for lexical and global hashes, both previously big and small.
22
23=head1 REFERENCE
24
25This test tests against RT ticket #26188
26
27L<http://rt.perl.org/rt3/Public/Bug/Display.html?id=26188>
28
29=cut
30
31use vars qw(%h_big %h_small);
32my %l_big = (1..50000);
33my %l_small = (1..10);
34
35%h_big = (1..50000);
36%h_small = (1..10);
37
38delete @h_big{keys %h_big};
39delete @h_small{keys %h_small};
40delete @l_big{keys %l_big};
41delete @l_small{keys %l_small};
42
43my $res = timethese shift || -3, {
44 big => '1 for keys %h_big',
45 small => '1 for keys %h_small',
46 scalar_big => '$a = keys %h_big',
47 scalar_small => '$a = keys %h_small',
48
49 lex_big => '1 for keys %l_big',
50 lex_small => '1 for keys %l_small',
51 lex_scalar_big => '$a = keys %l_big',
52 lex_scalar_small => '$a = keys %l_small',
53}, 'none';
54
55sub iters_per_second {
56 $_[0]->iters / $_[0]->cpu_p
57}
58
59sub about_as_fast_ok {
60 my ($res, $key1, $key2, $name) = @_;
61 $name ||= "Speed difference between $key1 and $key2 is less than 25%";
62 my %iters_per_second = map { $_ => iters_per_second( $res->{ $_ }) } ($key1, $key2);
63
64 my $ratio = abs(1 - $iters_per_second{ $key1 } / ($iters_per_second{ $key2 } || 1 ));
65 if (! cmp_ok( $ratio, '<', 0.25, $name )) {
66 diag( sprintf "%20s: %12.2f/s\n", $key1, $iters_per_second{ $key1 } );
67 diag( sprintf "%20s: %12.2f/s\n", $key2, $iters_per_second{ $key2 } );
68 };
69};
70
71about_as_fast_ok( $res, 'scalar_big', 'scalar_small',"Checking the count of hash keys in an empty hash (global)");
72
73about_as_fast_ok( $res, 'big', 'small', "Checking the list of hash keys in an empty hash (global)");
74
75about_as_fast_ok( $res, 'lex_scalar_big', 'lex_scalar_small',"Checking the count of hash keys in an empty hash (lexical)");
76
77about_as_fast_ok( $res, 'lex_big', 'lex_small', "Checking the list of hash keys in an empty hash (lexical)");
78
79about_as_fast_ok( $res, 'lex_scalar_big', 'scalar_big',"Checking the count of hash keys in an empty hash, global vs. lexical");
80
81about_as_fast_ok( $res, 'lex_big', 'big', "Checking the list of hash keys in an empty hash, global vs. lexical");
82
83__END__
84
85# code written
86 /* quick bailout if the hash is empty anyway.
87 I don't know if placeholders are included in the KEYS count, so a defensive check
88 */
1b95d04f 89 if (! HvUSEDKEYS(hv) && !(flags & HV_ITERNEXT_WANTPLACEHOLDERS) )
58da6fbc 90 return NULL;