Class-Accessor-Inherited-XS

 view release on metacpan or  search on metacpan

lib/Class/Accessor/Inherited/XS.pm  view on Meta::CPAN

    __PACKAGE__->new(foo => 1, bar => 2); # values are copied
    __PACKAGE__->new(\%args);             # values are not copied, much faster
    $obj->new(foo => 1, bar => 2);        # values are copied, but nothing is taken from $obj
    $obj->new(\%args);                    # values are not copied, and nothing is taken from $obj

=head1 UTF-8 AND BINARY SAFETY

Starting with the perl 5.16.0, this module provides full support for UTF-8 method names and hash keys.
But on older perls you can't distinguish UTF-8 strings from bytes string in method names, so accessors
with UTF-8 names can end up getting a wrong value. You have been warned.

Also, starting from 5.16.0 accessor installation is binary safe, except for the Windows platform.
This module croaks on attempts to install binary accessors on unsupported platforms.

=head1 THREADS

Though highly discouraged, perl threads are supported by L<Class::Accessor::Inherited::XS>. You can
have accessors with same names pointing to different keys in different threads, etc. There are
no known conceptual leaks.

=head1 PERFORMANCE

L<Class::Accessor::Inherited::XS> is at least 10x times faster than L<Class::Accessor::Grouped>, depending
on your usage pattern. Inherited accessors have constant speed even in large inheritance chains. Object accessors
are even faster than L<Class::XSAccessor> ones.

Accessors with just an empty sub callback are ~3x times slower then normal ones, so use them only when absolutely necessary.

Here are results from a benchmark run on perl 5.20.1 (see bench folder):

                       Rate pkg_gparent_cag pkg_cag obj_cag obj_caix_cb pkg_set_caix pkg_gparent_caix pkg_caix obj_cxa obj_caix obj_direct class_caix
pkg_gparent_cag    233829/s              --    -77%    -82%        -96%         -98%             -98%     -98%    -99%     -99%       -99%       -99%
pkg_cag           1022855/s            337%      --    -21%        -84%         -89%             -90%     -90%    -94%     -95%       -96%       -97%
obj_cag           1302727/s            457%     27%      --        -80%         -86%             -87%     -87%    -92%     -94%       -95%       -96%
obj_caix_cb       6377179/s           2627%    523%    390%          --         -33%             -36%     -37%    -62%     -69%       -76%       -80%
pkg_set_caix      9538400/s           3979%    833%    632%         50%           --              -4%      -6%    -43%     -54%       -64%       -70%
pkg_gparent_caix  9914704/s           4140%    869%    661%         55%           4%               --      -2%    -41%     -52%       -62%       -68%
pkg_caix         10138654/s           4236%    891%    678%         59%           6%               2%       --    -40%     -51%       -61%       -68%
obj_cxa          16858257/s           7110%   1548%   1194%        164%          77%              70%      66%      --     -19%       -36%       -46%
obj_caix         20811071/s           8800%   1935%   1498%        226%         118%             110%     105%     23%       --       -20%       -34%
obj_direct       26145035/s          11081%   2456%   1907%        310%         174%             164%     158%     55%      26%         --       -16%
class_caix       31300776/s          13286%   2960%   2303%        391%         228%             216%     209%     86%      50%        20%         --


=head1 EXTENDING

    package MyAccessor;
    # 'register_type' isn't exported
    use Class::Accessor::Inherited::XS::Constants;
    Class::Accessor::Inherited::XS::register_type(
        inherited_cb => {on_read => sub {}, on_write => sub{}, opts => $bitset},
    );

    package MyClass;
    use MyAccessor;
    use Class::Accessor::Inherited::XS {
        inherited    => ['foo'],
        inherited_cb => ['bar'],
    };

You can register new inherited accessor types with associated read/write callbacks. Unlike
L<Class::Accessor::Grouped>, only a single callback can be set for a type, without per-class
B<get_$type>/B<set_$type> lookups. You can omit either B<on_read> or B<on_write> if you don't
need it to avoid performance losses from associated call.

B<on_read> callback receives a single argument - return value from the underlying B<inherited> accessor. It's result
is the new accessor's return value (and it isn't stored anywhere).

B<on_write> callback receives original accessor's arguments, and it's return value is stored as usual.
Exceptions thrown from this callback will cancel store and will leave old value unchanged.

You can specify additional flags with the 'opts' key. Currently only IsNamed is supported - with it the accessor callback
is invoked with it's name passed as an additional argument. This can be useful when creating a proxy.

=head1 PROFILING WITH Devel::NYTProf

To perform it's task, L<Devel::NYTProf> hooks into the perl interpreter by replacing default behaviour for subroutine calls
at the opcode level. To squeeze last bits of performance, L<Class::Accessor::Inherited::XS> does the same, but separately
on each call site of its accessors. It turns out into CAIX favor - L<Devel::NYTProf> sees only the first call to CAIX
accessor, but all subsequent ones become invisible to the subs profiler.

Note that the statement profiler still correctly accounts for the time spent on each line, you just don't see time spent in accessors'
calls separately. That's sometimes OK, sometimes not - you get profile with all possible optimizations on, but it's not easy to comprehend.

Since it's hard to detect L<Devel::NYTProf> (and any other module doing such magic) in a portable way (all hail Win32), there's
an %ENV switch available - you can set CAIXS_DISABLE_ENTERSUB to a true value to disable opcode optimizations and get a full subs profile.

=head1 CAVEATS

When using B<varclass> accessors, do not clear or alias C<*__PACKAGE__::accessor> glob - that will break aliasing between accessor storage
and $__PACKAGE__::accessor variable. While the stored value is still accessible through accessor, it effectively becomes a B<class> one.

=head1 SEE ALSO

=over

=item * L<Class::Accessor::Grouped>

=item * L<Class::XSAccessor>

=back

=head1 COPYRIGHT AND LICENSE

Copyright (C) 2009 by Vladimir Timofeev

Copyright (C) 2014-2018 by Sergey Aleynikov

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.10.1 or,
at your option, any later version of Perl 5 you may have available.

=cut



( run in 1.864 second using v1.01-cache-2.11-cpan-39bf76dae61 )