line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
35
|
|
|
35
|
|
114240
|
use 5.012; |
|
35
|
|
|
|
|
323
|
|
2
|
35
|
|
|
35
|
|
187
|
use strict; |
|
35
|
|
|
|
|
61
|
|
|
35
|
|
|
|
|
717
|
|
3
|
35
|
|
|
35
|
|
219
|
use warnings; |
|
35
|
|
|
|
|
70
|
|
|
35
|
|
|
|
|
3745
|
|
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
our $AUTHORITY = 'cpan:TOBYINK'; |
7
|
|
|
|
|
|
|
our $VERSION = '0.001'; |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
use Type::Tiny::XS (); |
10
|
35
|
|
|
35
|
|
15987
|
|
|
35
|
|
|
|
|
120842
|
|
|
35
|
|
|
|
|
10553
|
|
11
|
|
|
|
|
|
|
my ( $specio_object, $xs_name, $tamper_inlined_too ) = @_; |
12
|
|
|
|
|
|
|
$specio_object or return; |
13
|
350
|
|
|
350
|
0
|
742
|
|
14
|
350
|
50
|
|
|
|
841
|
my $coderef = Type::Tiny::XS::get_coderef_for( $xs_name ); |
15
|
|
|
|
|
|
|
my $subname = Type::Tiny::XS::get_subname_for( $xs_name ); |
16
|
350
|
|
|
|
|
2019
|
$coderef or return; |
17
|
350
|
|
|
|
|
3496
|
|
18
|
350
|
50
|
|
|
|
2239
|
$specio_object->{_xs_name} = $xs_name; |
19
|
|
|
|
|
|
|
$specio_object->{_optimized_constraint} = $coderef; |
20
|
350
|
|
|
|
|
887
|
|
21
|
350
|
|
|
|
|
608
|
if ( $tamper_inlined_too ) { |
22
|
|
|
|
|
|
|
$specio_object->{_inline_generator} = sub { |
23
|
350
|
100
|
|
|
|
722
|
my ( undef, $var ) = @_; |
24
|
|
|
|
|
|
|
return "$subname($var)"; |
25
|
198
|
|
|
198
|
|
15290401
|
}; |
26
|
198
|
|
|
|
|
1418
|
} |
27
|
140
|
|
|
|
|
637
|
} |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
use Specio::Library::Builtins; |
30
|
|
|
|
|
|
|
my $exported = Specio::Exporter::exportable_types_for_package( 'Specio::Library::Builtins' ); |
31
|
35
|
|
|
35
|
|
19047
|
|
|
35
|
|
|
|
|
3577420
|
|
|
35
|
|
|
|
|
434
|
|
32
|
|
|
|
|
|
|
# Many similarly named types differ between Specio and Types::Common, |
33
|
|
|
|
|
|
|
# and only these seem to be exactly equivalent. This is mostly because |
34
|
|
|
|
|
|
|
# Specio accepts overloaded objects in place of primatives everywhere. |
35
|
|
|
|
|
|
|
# |
36
|
|
|
|
|
|
|
tamper $exported->{'Item'}, 'Any'; |
37
|
|
|
|
|
|
|
tamper $exported->{'Defined'}, 'Defined'; |
38
|
|
|
|
|
|
|
tamper $exported->{'Undef'}, 'Undef'; |
39
|
|
|
|
|
|
|
tamper $exported->{'Ref'}, 'Ref'; |
40
|
|
|
|
|
|
|
tamper $exported->{'Value'}, 'Value'; |
41
|
|
|
|
|
|
|
tamper $exported->{'Object'}, 'Object'; |
42
|
|
|
|
|
|
|
tamper $exported->{'ArrayRef'}, 'ArrayLike', !!1; |
43
|
|
|
|
|
|
|
tamper $exported->{'HashRef'}, 'HashLike', !!1; |
44
|
|
|
|
|
|
|
tamper $exported->{'CodeRef'}, 'CodeLike', !!1; |
45
|
|
|
|
|
|
|
tamper $exported->{'Str'}, 'StringLike', !!1; |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
# You thought that was bad? It's about to get worse! |
48
|
|
|
|
|
|
|
# |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
do { |
51
|
|
|
|
|
|
|
my $orig = $exported->{'ArrayRef'}{_parameterized_inline_generator}; |
52
|
|
|
|
|
|
|
$exported->{'ArrayRef'}{_parameterized_inline_generator} = sub { |
53
|
|
|
|
|
|
|
my ( $type, $parameter, $var ) = @_; |
54
|
|
|
|
|
|
|
my $param_check = $parameter->_optimized_constraint; |
55
|
|
|
|
|
|
|
if ( my $name = Type::Tiny::XS::is_known($param_check) ) { |
56
|
|
|
|
|
|
|
my $xsub = Type::Tiny::XS::get_coderef_for( "ArrayLike[$name]" ); |
57
|
|
|
|
|
|
|
if ( $xsub ) { |
58
|
|
|
|
|
|
|
$type->{_optimized_constraint} = $xsub; |
59
|
|
|
|
|
|
|
my $xsubname = Type::Tiny::XS::get_subname_for( "ArrayLike[$name]" ); |
60
|
|
|
|
|
|
|
return "$xsubname($var)" if $xsubname; |
61
|
|
|
|
|
|
|
} |
62
|
|
|
|
|
|
|
} |
63
|
|
|
|
|
|
|
goto $orig; |
64
|
|
|
|
|
|
|
}; |
65
|
|
|
|
|
|
|
}; |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
do { |
68
|
|
|
|
|
|
|
my $orig = $exported->{'HashRef'}{_parameterized_inline_generator}; |
69
|
|
|
|
|
|
|
$exported->{'HashRef'}{_parameterized_inline_generator} = sub { |
70
|
|
|
|
|
|
|
my ( $type, $parameter, $var ) = @_; |
71
|
|
|
|
|
|
|
my $param_check = $parameter->_optimized_constraint; |
72
|
|
|
|
|
|
|
if ( my $name = Type::Tiny::XS::is_known($param_check) ) { |
73
|
|
|
|
|
|
|
my $xsub = Type::Tiny::XS::get_coderef_for( "HashLike[$name]" ); |
74
|
|
|
|
|
|
|
if ( $xsub ) { |
75
|
|
|
|
|
|
|
$type->{_optimized_constraint} = $xsub; |
76
|
|
|
|
|
|
|
my $xsubname = Type::Tiny::XS::get_subname_for( "HashLike[$name]" ); |
77
|
|
|
|
|
|
|
return "$xsubname($var)" if $xsubname; |
78
|
|
|
|
|
|
|
} |
79
|
|
|
|
|
|
|
} |
80
|
|
|
|
|
|
|
goto $orig; |
81
|
|
|
|
|
|
|
}; |
82
|
|
|
|
|
|
|
}; |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
do { |
85
|
|
|
|
|
|
|
use Specio::Constraint::ObjectIsa (); |
86
|
|
|
|
|
|
|
no warnings 'redefine'; |
87
|
35
|
|
|
35
|
|
364815
|
my $orig = \&Specio::Constraint::ObjectIsa::_build_inline_generator; |
|
35
|
|
|
|
|
666809
|
|
|
35
|
|
|
|
|
1100
|
|
88
|
35
|
|
|
35
|
|
270
|
*Specio::Constraint::ObjectIsa::_build_inline_generator = sub { |
|
35
|
|
|
|
|
77
|
|
|
35
|
|
|
|
|
6033
|
|
89
|
|
|
|
|
|
|
return sub { |
90
|
|
|
|
|
|
|
my ( $type, $var ) = @_; |
91
|
|
|
|
|
|
|
my $class = $type->class; |
92
|
5
|
|
|
5
|
|
9244
|
my $xsub = Type::Tiny::XS::get_coderef_for("InstanceOf[$class]"); |
93
|
5
|
|
|
|
|
19
|
if ( $xsub ) { |
94
|
5
|
|
|
|
|
43
|
$type->{_optimized_constraint} = $xsub; |
95
|
5
|
50
|
|
|
|
264
|
my $xsubname = Type::Tiny::XS::get_subname_for("InstanceOf[$class]"); |
96
|
5
|
|
|
|
|
20
|
return "$xsubname($var)" if $xsubname; |
97
|
5
|
|
|
|
|
23
|
} |
98
|
5
|
50
|
|
|
|
66
|
goto $orig; |
99
|
|
|
|
|
|
|
}; |
100
|
0
|
|
|
|
|
0
|
}; |
101
|
4
|
|
|
4
|
|
1338058
|
}; |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
do { |
104
|
|
|
|
|
|
|
use Specio::Constraint::ObjectCan (); |
105
|
|
|
|
|
|
|
no warnings 'redefine'; |
106
|
35
|
|
|
35
|
|
16193
|
my $orig = \&Specio::Constraint::ObjectCan::_build_inline_generator; |
|
35
|
|
|
|
|
674820
|
|
|
35
|
|
|
|
|
1113
|
|
107
|
35
|
|
|
35
|
|
269
|
*Specio::Constraint::ObjectCan::_build_inline_generator = sub { |
|
35
|
|
|
|
|
94
|
|
|
35
|
|
|
|
|
9206
|
|
108
|
|
|
|
|
|
|
return sub { |
109
|
|
|
|
|
|
|
my ( $type, $var ) = @_; |
110
|
|
|
|
|
|
|
my $methods = join q{,}, @{ $type->methods }; |
111
|
9
|
|
|
9
|
|
17086
|
my $xsub = Type::Tiny::XS::get_coderef_for("HasMethods[$methods]"); |
112
|
9
|
|
|
|
|
21
|
if ( $xsub ) { |
|
9
|
|
|
|
|
27
|
|
113
|
9
|
|
|
|
|
75
|
$type->{_optimized_constraint} = $xsub; |
114
|
9
|
50
|
|
|
|
367
|
my $xsubname = Type::Tiny::XS::get_subname_for("HasMethods[$methods]"); |
115
|
9
|
|
|
|
|
44
|
return "$xsubname($var)" if $xsubname; |
116
|
9
|
|
|
|
|
40
|
} |
117
|
9
|
50
|
|
|
|
101
|
goto $orig; |
118
|
|
|
|
|
|
|
}; |
119
|
0
|
|
|
|
|
0
|
}; |
120
|
5
|
|
|
5
|
|
1527964
|
}; |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
1; |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
=pod |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
=encoding utf-8 |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
=head1 NAME |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
SpecioX::XS - [PROOF OF CONCEPT] speed boost for Specio using Type::Tiny::XS |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
=head1 SYNOPSIS |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
A rather contrived benchmark, using a type constraint which in L<Types::Common> |
136
|
|
|
|
|
|
|
would be called B<< ArrayLike[HashLike[StringLike]] >>, so an arrayref of |
137
|
|
|
|
|
|
|
hashrefs of strings, but which allows objects overloading C<< %{} >>, |
138
|
|
|
|
|
|
|
C<< @{} >>, and C<< "" >>. |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
# bin/benchmark.pl |
141
|
|
|
|
|
|
|
# |
142
|
|
|
|
|
|
|
use Benchmark; |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
timethis( -3, q{ |
145
|
|
|
|
|
|
|
use Specio::Library::Builtins; |
146
|
|
|
|
|
|
|
my $type = t( 'ArrayRef', of => t( 'HashRef', of => t( 'Str' ) ) ); |
147
|
|
|
|
|
|
|
my $arr = [ map { foo => $_ }, 1 .. 100 ]; |
148
|
|
|
|
|
|
|
for ( 0 .. 100 ) { |
149
|
|
|
|
|
|
|
$type->check( $arr ) or die; |
150
|
|
|
|
|
|
|
} |
151
|
|
|
|
|
|
|
} ); |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
And running the benchmarks: |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
$ perl -Ilib bin/benchmark.pl |
156
|
|
|
|
|
|
|
timethis for 3: 3 wallclock secs ( 3.20 usr + 0.00 sys = 3.20 CPU) @ 271.25/s (n=868) |
157
|
|
|
|
|
|
|
$ perl -Ilib -MSpecioX::XS bin/benchmark.pl |
158
|
|
|
|
|
|
|
timethis for 3: 4 wallclock secs ( 3.48 usr + 0.01 sys = 3.49 CPU) @ 918.91/s (n=3207) |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
On my laptop, the check runs more than three times faster with L<SpecioX::XS>. |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
=head1 DESCRIPTION |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
This module pokes around in Specio internals quite badly. |
165
|
|
|
|
|
|
|
Do not use it in production situations. |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
=head1 BUGS |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
Please report any bugs to |
170
|
|
|
|
|
|
|
L<http://rt.cpan.org/Dist/Display.html?Queue=SpecioX-XS>. |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
=head1 SEE ALSO |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
L<Specio>, L<Type::Tiny::XS>. |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
=head1 AUTHOR |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
Toby Inkster E<lt>tobyink@cpan.orgE<gt>. |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENCE |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
This software is copyright (c) 2022 by Toby Inkster. |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
This is free software; you can redistribute it and/or modify it under |
185
|
|
|
|
|
|
|
the same terms as the Perl 5 programming language system itself. |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
=head1 DISCLAIMER OF WARRANTIES |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED |
190
|
|
|
|
|
|
|
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF |
191
|
|
|
|
|
|
|
MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. |