%PDF- %PDF-
Direktori : /home/opti/perl5/lib/perl5/Type/Tiny/Manual/ |
Current File : /home/opti/perl5/lib/perl5/Type/Tiny/Manual/Optimization.pod |
=pod =for stopwords smush smushed enums =encoding utf-8 =head1 NAME Type::Tiny::Manual::Optimization - squeeze the most out of your CPU =head1 DESCRIPTION Various tips to help you squeeze the most out of your CPU. =head2 XS The simplest thing you can do to increase performance of many of the built-in type constraints is to install L<Type::Tiny::XS>, a set of ultra-fast type constraint checks implemented in C. L<Type::Tiny> will attempt to load L<Type::Tiny::XS> and use its type checks. If L<Type::Tiny::XS> is not available, it will then try to use L<Mouse> B<< if it is already loaded >>, but Type::Tiny won't attempt to load Mouse for you. =head3 Types that can be accelerated by Type::Tiny::XS The following simple type constraints from L<Types::Standard> will be accelerated by Type::Tiny::XS: C<Any>, C<ArrayRef>, C<Bool>, C<ClassName>, C<CodeRef>, C<Defined>, C<FileHandle>, C<GlobRef>, C<HashRef>, C<Int>, C<Item>, C<Object>, C<Map>, C<Ref>, C<ScalarRef>, C<Str>, C<Tuple>, C<Undef>, and C<Value>. (Note that C<Num> and C<RegexpRef> are B<not> on that list.) The parameterized form of C<Ref> cannot be accelerated. The parameterized forms of C<ArrayRef>, C<HashRef>, and C<Map> can be accelerated only if their parameters are. The parameterized form of C<Tuple> can be accelerated if its parameters are, it has no C<Optional> components, and it does not use C<slurpy>. Certain type constraints may benefit partially from Type::Tiny::XS. For example, C<RoleName> inherits from C<ClassName>, so part of the type check will be conducted by Type::Tiny::XS. The parameterized C<InstanceOf>, C<HasMethods>, and C<Enum> type constraints will be accelerated. So will L<Type::Tiny::Class>, L<Type::Tiny::Duck>, and L<Type::Tiny::Enum> objects. (But enums will only be accelerated if the list of allowed string values consist entirely of word characters and hyphens - that is: C<< not grep /[^\w-]/, @values >>.) The C<PositiveInt> and C<PositiveOrZeroInt> type constraints from L<Types::Common::Numeric> will be accelerated, as will the C<NonEmptyStr> type constraint from L<Types::Common::String>. L<Type::Tiny::Union> and L<Type::Tiny::Intersection> will also be accelerated if their constituent type constraints are. =head3 Types that can be accelerated by Mouse The following simple type constraints from L<Types::Standard> will be accelerated by Type::Tiny::XS: C<Any>, C<ArrayRef>, C<Bool>, C<ClassName>, C<CodeRef>, C<Defined>, C<FileHandle>, C<GlobRef>, C<HashRef>, C<Ref>, C<ScalarRef>, C<Str>, C<Undef>, and C<Value>. (Note that C<Item>, C<Num>, C<Int>, C<Object>, and C<RegexpRef> are B<not> on that list.) The parameterized form of C<Ref> cannot be accelerated. The parameterized forms of C<ArrayRef> and C<HashRef> can be accelerated only if their parameters are. Certain type constraints may benefit partially from Mouse. For example, C<RoleName> inherits from C<ClassName>, so part of the type check will be conducted by Mouse. The parameterized C<InstanceOf> and C<HasMethods> type constraints will be accelerated. So will L<Type::Tiny::Class> and L<Type::Tiny::Duck> objects. =head2 Common Sense The C<< HashRef[ArrayRef] >> type constraint can probably be checked faster than C<< HashRef[ArrayRef[Num]] >>. If you find yourself using very complex and slow type constraints, you should consider switching to simpler and faster ones. (Though this means you have to place a little more trust in your caller to not supply you with bad data.) (A counter-intuitive exception to this: even though C<Int> is more restrictive than C<Num>, in most circumstances C<Int> checks will run faster.) =head2 Inlining Type Constraints If your type constraint can be inlined, this can not only speed up Type::Tiny's own checks and coercions, it may also allow your type constraint to be inlined into generated methods such as Moose attribute accessors. All of the constraints from C<Types::Standard> can be inlined, as can enum, class_type, role_type and duck_type constraints. Union and intersection constraints can be inlined if their sub-constraints can be. So if you can define your own types purely in terms of these types, you automatically get inlining: declare HashLike, as union [ Ref["HASH"], Overload["&{}"], ]; However, sometimes these base types are not powerful enough and you'll need to write a constraint coderef: declare NonEmptyHash, as HashLike, where { scalar values %$_ }; ... and you've suddenly sacrificed a lot of speed. Inlining to the rescue! You can define an inlining coderef which will be passed two parameters: the constraint itself and a variable name as a string. For example, the variable name might be C<< '$_' >> or C<< '$_[0]' >>. Your coderef should return a Perl expression string, interpolating that variable name. declare NonEmptyHash, as HashLike, where { scalar values %$_ }, inline_as { my ($constraint, $varname) = @_; return sprintf( '%s and scalar values %%{%s}', $constraint->parent->inline_check($varname), $varname, ); }; The Perl expression could be inlined within a function or a C<if> clause or potentially anywhere, so it really must be an expression, not a statement. It should not C<return> or C<exit> and probably shouldn't C<die>. (If you need loops and so on, you can output a C<do> block.) Note that if you're subtyping an existing type constraint, your C<inline_as> block is also responsible for checking the parent type's constraint. This can be done quite easily, as shown in the example above. Note that defining a type constraint in terms of a constraint coderef and an inlining coderef can be a little repetitive. L<Sub::Quote> provides an alternative that reduces repetition (though the inlined code might not be as compact/good/fast). declare NonEmptyHash, as HashLike, constraint => quote_sub q{ scalar values %$_ }; Aside: it's been pointed out that "might not be as fast" above is a bit hand-wavy. When Type::Tiny does inlining from Sub::Quote coderefs, it needs to inline all the ancestor type constraints, and smush them together with C<< && >>. This may result in duplicate checks. For example, if 'MyArray' inherits from 'MyRef' which inherits from 'MyDef', the inlined code might end up as: defined($_) # check MyDef && ref($_) # check MyRef && ref($_) eq 'ARRAY' # check MyArray When just the last check would have been sufficient. A custom C<inline_as> allows you finer control over how the type constraint is inlined. =head2 Optimizing Coercions Coercions are often defined using coderefs: PathTiny->plus_coercions( Str, sub { "Path::Tiny"->new($_) }, Undef, sub { "Path::Tiny"->new("/etc/myapp/default.conf") }, ); But you can instead define them as strings of Perl code operating on C<< $_ >>: PathTiny->plus_coercions( Str, q{ "Path::Tiny"->new($_) }, Undef, q{ "Path::Tiny"->new("/etc/myapp/default.conf") }, ); The latter will run faster, so is preferable at least for simple coercions. This makes the most difference when used with L<Moo>, which supports inlining of coercions. L<Moose> does not inline coercions, but providing coercions as strings still allows Type::Tiny to optimize the coercion coderef it provides to Moose. =head1 AUTHOR Toby Inkster E<lt>tobyink@cpan.orgE<gt>. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014, 2017-2018 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. =cut