NAME
Type::Tiny::Manual::Optimization - squeeze the most out of your CPU
MANUAL
Type::Tiny is written with efficiency in mind, but there are techniques you can use to get the best performance out of it.
XS
The simplest thing you can do to increase performance of many of the built-in type constraints is to install Type::Tiny::XS, a set of ultra-fast type constraint checks implemented in C.
Type::Tiny will attempt to load Type::Tiny::XS and use its type checks. If Type::Tiny::XS is not available, it will then try to use Mouse if it is already loaded, but Type::Tiny won't attempt to load Mouse for you.
Certain type constraints can also be accelerated if you have Ref::Util::XS installed.
Types that can be accelerated by Type::Tiny::XS
The following simple type constraints from Types::Standard will be accelerated by Type::Tiny::XS: Any
, ArrayRef
, Bool
, ClassName
, CodeRef
, Defined
, FileHandle
, GlobRef
, HashRef
, Int
, Item
, Object
, Map
, Ref
, ScalarRef
, Str
, Tuple
, Undef
, and Value
. (Note that Num
and RegexpRef
are not on that list.)
The parameterized form of Ref
cannot be accelerated.
The parameterized forms of ArrayRef
, HashRef
, and Map
can be accelerated only if their parameters are.
The parameterized form of Tuple
can be accelerated if its parameters are, it has no Optional
components, and it does not use slurpy
.
Certain type constraints may benefit partially from Type::Tiny::XS. For example, RoleName
inherits from ClassName
, so part of the type check will be conducted by Type::Tiny::XS.
The parameterized InstanceOf
, HasMethods
, and Enum
type constraints will be accelerated. So will Type::Tiny::Class, Type::Tiny::Duck, and 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: not grep /[^\w-]/, @values
.)
The PositiveInt
and PositiveOrZeroInt
type constraints from Types::Common::Numeric will be accelerated, as will the NonEmptyStr
type constraint from Types::Common::String.
Type::Tiny::Union and Type::Tiny::Intersection will also be accelerated if their constituent type constraints are.
Types that can be accelerated by Mouse
The following simple type constraints from Types::Standard will be accelerated by Type::Tiny::XS: Any
, ArrayRef
, Bool
, ClassName
, CodeRef
, Defined
, FileHandle
, GlobRef
, HashRef
, Ref
, ScalarRef
, Str
, Undef
, and Value
. (Note that Item
, Num
, Int
, Object
, and RegexpRef
are not on that list.)
The parameterized form of Ref
cannot be accelerated.
The parameterized forms of ArrayRef
and HashRef
can be accelerated only if their parameters are.
Certain type constraints may benefit partially from Mouse. For example, RoleName
inherits from ClassName
, so part of the type check will be conducted by Mouse.
The parameterized InstanceOf
and HasMethods
type constraints will be accelerated. So will Type::Tiny::Class and Type::Tiny::Duck objects.
Inlining Type Constraints
TODO
Inlining Coercions
TODO
Common Sense
The HashRef[ArrayRef]
type constraint can probably be checked faster than 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 Int
is more restrictive than Num
, in most circumstances Int
checks will run faster.)
Devel::StrictMode
One possibility is to use strict type checks when you're running your release tests, and faster, more permissive type checks at other times. Devel::StrictMode can make this easier.
This provides a STRICT
constant that indicates whether your code is operating in "strict mode" based on certain environment variables.
Attributes
use Types::Standard qw( ArrayRef Num );
use Devel::StrictMode qw( STRICT );
has numbers => (
is => 'ro',
isa => STRICT ? ArrayRef[Num] : ArrayRef,
default => sub { [] },
);
It is inadvisible to do this on attributes that have coercions because it can lead to inconsistent and unpredictable behaviour.
Type::Params
use Types::Standard qw( Num Object );
use Type::Params qw( compile );
use Devel::StrictMode qw( STRICT );
sub add_number {
state $check;
$check = compile(Object, Num) if STRICT;
my ($self, $num) = STRICT ? $check->(@_) : @_;
push @{ $self->numbers }, $num;
return $self;
}
Again, you need to be careful to ensure consistent behaviour if you're using coercions, defaults, slurpies, etc.
Ad-Hoc Type Checks
...;
my $x = get_some_number();
assert_Int($x) if STRICT;
return $x + 1;
...;
NEXT STEPS
Here's your next step:
-
Advanced information on coercions.
AUTHOR
Toby Inkster <tobyink@cpan.org>.
COPYRIGHT AND LICENCE
This software is copyright (c) 2013-2014, 2017-2019 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.
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.