Filename | /usr/share/perl5/Class/Accessor/Grouped.pm |
Statements | Executed 21 statements in 104µs |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
927 | 1 | 1 | 526ms | 592ms | __ANON__[:774] | Class::Accessor::Grouped::
1920 | 1 | 1 | 111ms | 851ms | _mk_group_accessors | Class::Accessor::Grouped::
3932 | 1 | 1 | 62.8ms | 677ms | __ANON__[:942] | Class::Accessor::Grouped::
3932 | 1 | 1 | 25.5ms | 703ms | make_group_accessor | Class::Accessor::Grouped::
1920 | 18 | 9 | 23.7ms | 874ms | mk_group_accessors | Class::Accessor::Grouped::
3450 | 2 | 2 | 21.4ms | 24.3ms | get_inherited | Class::Accessor::Grouped::
927 | 1 | 1 | 6.57ms | 8.92ms | __ANON__[:708] | Class::Accessor::Grouped::
3933 | 3 | 1 | 6.16ms | 6.16ms | CORE:match (opcode) | Class::Accessor::Grouped::
720 | 4 | 4 | 2.44ms | 2.56ms | set_inherited | Class::Accessor::Grouped::
927 | 1 | 1 | 2.35ms | 2.35ms | perlstring | __CAG_ENV__::
182 | 1 | 1 | 1.90ms | 2.43ms | get_super_paths | Class::Accessor::Grouped::
4 | 3 | 2 | 97µs | 308µs | _result_class | DBIx::Class::ResultSet::
1 | 1 | 1 | 87µs | 278µs | debug | DBIx::Class::Storage::
2 | 2 | 2 | 80µs | 240µs | result_source | DBIx::Class::ResultSet::
3 | 3 | 2 | 78µs | 248µs | _dbh_autocommit | DBIx::Class::Storage::DBI::
1 | 1 | 1 | 76µs | 2.09ms | BEGIN@31 | Class::Accessor::Grouped::
1 | 1 | 1 | 62µs | 78µs | BEGIN@872 | Class::Accessor::Grouped::
1 | 1 | 1 | 60µs | 179µs | source_name | DBIx::Class::ResultSource::
3 | 3 | 2 | 60µs | 176µs | _conn_pid | DBIx::Class::Storage::DBI::
1 | 1 | 1 | 56µs | 160µs | _primaries | DBIx::Class::ResultSource::
1 | 1 | 1 | 54µs | 200µs | schema | DBIx::Class::Storage::
1 | 1 | 1 | 53µs | 198µs | name | DBIx::Class::ResultSource::
1 | 1 | 1 | 51µs | 167µs | on_connect_call | DBIx::Class::Storage::DBI::
3 | 3 | 2 | 50µs | 160µs | _driver_determined | DBIx::Class::Storage::DBI::
1 | 1 | 1 | 47µs | 154µs | _relationships | DBIx::Class::ResultSource::
10 | 9 | 3 | 43µs | 112µs | _dbh | DBIx::Class::Storage::DBI::
3 | 3 | 2 | 41µs | 127µs | unsafe | DBIx::Class::Storage::DBI::
3 | 3 | 3 | 38µs | 101µs | _dbic_connect_attributes | DBIx::Class::Storage::DBI::
3 | 3 | 2 | 34µs | 164µs | _dbh_details | DBIx::Class::Storage::DBI::
3 | 3 | 2 | 34µs | 99µs | _sql_maker_opts | DBIx::Class::Storage::DBI::
1 | 1 | 1 | 34µs | 103µs | transaction_depth | DBIx::Class::Storage::
3 | 3 | 2 | 33µs | 110µs | _connect_info | DBIx::Class::Storage::DBI::
1 | 1 | 1 | 31µs | 97µs | _unique_constraints | DBIx::Class::ResultSource::
3 | 3 | 2 | 30µs | 93µs | on_connect_do | DBIx::Class::Storage::DBI::
2 | 2 | 2 | 30µs | 93µs | _sql_maker | DBIx::Class::Storage::DBI::
1 | 1 | 1 | 30µs | 98µs | _ordered_columns | DBIx::Class::ResultSource::
1 | 1 | 1 | 28µs | 86µs | _columns | DBIx::Class::ResultSource::
1 | 1 | 1 | 14µs | 20µs | BEGIN@2 | Class::Accessor::Grouped::
1 | 1 | 1 | 11µs | 18µs | BEGIN@377 | Class::Accessor::Grouped::
1 | 1 | 1 | 11µs | 16µs | BEGIN@894 | Class::Accessor::Grouped::
1 | 1 | 1 | 10µs | 17µs | BEGIN@87 | Class::Accessor::Grouped::
1 | 1 | 1 | 9µs | 20µs | BEGIN@895 | Class::Accessor::Grouped::
1 | 1 | 1 | 9µs | 15µs | BEGIN@418 | Class::Accessor::Grouped::
1 | 1 | 1 | 8µs | 19µs | BEGIN@378 | Class::Accessor::Grouped::
1 | 1 | 1 | 8µs | 17µs | BEGIN@88 | Class::Accessor::Grouped::
1 | 1 | 1 | 7µs | 10µs | BEGIN@3 | Class::Accessor::Grouped::
1 | 1 | 1 | 4µs | 4µs | BEGIN@8 | Class::Accessor::Grouped::
1 | 1 | 1 | 4µs | 4µs | BEGIN@5 | Class::Accessor::Grouped::
1 | 1 | 1 | 4µs | 4µs | BEGIN@6 | Class::Accessor::Grouped::
1 | 1 | 1 | 4µs | 4µs | BEGIN@4 | Class::Accessor::Grouped::
1 | 1 | 1 | 3µs | 3µs | BEGIN@23 | Class::Accessor::Grouped::
2 | 2 | 1 | 2µs | 2µs | __ANON__ (xsub) | __CAG_ENV__::
0 | 0 | 0 | 0s | 0s | CLONE | Class::Accessor::Grouped::
0 | 0 | 0 | 0s | 0s | __ANON__[:728] | Class::Accessor::Grouped::
0 | 0 | 0 | 0s | 0s | __ANON__[:748] | Class::Accessor::Grouped::
0 | 0 | 0 | 0s | 0s | __ANON__[:914] | Class::Accessor::Grouped::
0 | 0 | 0 | 0s | 0s | get_component_class | Class::Accessor::Grouped::
0 | 0 | 0 | 0s | 0s | get_simple | Class::Accessor::Grouped::
0 | 0 | 0 | 0s | 0s | make_group_ro_accessor | Class::Accessor::Grouped::
0 | 0 | 0 | 0s | 0s | make_group_wo_accessor | Class::Accessor::Grouped::
0 | 0 | 0 | 0s | 0s | mk_group_ro_accessors | Class::Accessor::Grouped::
0 | 0 | 0 | 0s | 0s | mk_group_wo_accessors | Class::Accessor::Grouped::
0 | 0 | 0 | 0s | 0s | set_component_class | Class::Accessor::Grouped::
0 | 0 | 0 | 0s | 0s | set_simple | Class::Accessor::Grouped::
0 | 0 | 0 | 0s | 0s | __result_class_accessor | DBIx::Class::ResultSet::
0 | 0 | 0 | 0s | 0s | _result_source_accessor | DBIx::Class::ResultSet::
0 | 0 | 0 | 0s | 0s | __columns_accessor | DBIx::Class::ResultSource::
0 | 0 | 0 | 0s | 0s | __ordered_columns_accessor | DBIx::Class::ResultSource::
0 | 0 | 0 | 0s | 0s | __primaries_accessor | DBIx::Class::ResultSource::
0 | 0 | 0 | 0s | 0s | __relationships_accessor | DBIx::Class::ResultSource::
0 | 0 | 0 | 0s | 0s | __unique_constraints_accessor | DBIx::Class::ResultSource::
0 | 0 | 0 | 0s | 0s | _column_info_from_storage_accessor | DBIx::Class::ResultSource::
0 | 0 | 0 | 0s | 0s | _name_accessor | DBIx::Class::ResultSource::
0 | 0 | 0 | 0s | 0s | _resultset_attributes_accessor | DBIx::Class::ResultSource::
0 | 0 | 0 | 0s | 0s | _source_info_accessor | DBIx::Class::ResultSource::
0 | 0 | 0 | 0s | 0s | _source_name_accessor | DBIx::Class::ResultSource::
0 | 0 | 0 | 0s | 0s | column_info_from_storage | DBIx::Class::ResultSource::
0 | 0 | 0 | 0s | 0s | resultset_attributes | DBIx::Class::ResultSource::
0 | 0 | 0 | 0s | 0s | source_info | DBIx::Class::ResultSource::
0 | 0 | 0 | 0s | 0s | __detached_source_accessor | DBIx::Class::ResultSourceHandle::
0 | 0 | 0 | 0s | 0s | _detached_source | DBIx::Class::ResultSourceHandle::
0 | 0 | 0 | 0s | 0s | _schema_accessor | DBIx::Class::ResultSourceHandle::
0 | 0 | 0 | 0s | 0s | _source_moniker_accessor | DBIx::Class::ResultSourceHandle::
0 | 0 | 0 | 0s | 0s | schema | DBIx::Class::ResultSourceHandle::
0 | 0 | 0 | 0s | 0s | source_moniker | DBIx::Class::ResultSourceHandle::
0 | 0 | 0 | 0s | 0s | _in_storage_accessor | DBIx::Class::Row::
0 | 0 | 0 | 0s | 0s | in_storage | DBIx::Class::Row::
0 | 0 | 0 | 0s | 0s | _limit_dialect_accessor | DBIx::Class::SQLMaker::
0 | 0 | 0 | 0s | 0s | _name_sep_accessor | DBIx::Class::SQLMaker::
0 | 0 | 0 | 0s | 0s | _quote_char_accessor | DBIx::Class::SQLMaker::
0 | 0 | 0 | 0s | 0s | limit_dialect | DBIx::Class::SQLMaker::
0 | 0 | 0 | 0s | 0s | name_sep | DBIx::Class::SQLMaker::
0 | 0 | 0 | 0s | 0s | quote_char | DBIx::Class::SQLMaker::
0 | 0 | 0 | 0s | 0s | __autoinc_supplied_for_op_accessor | DBIx::Class::Storage::DBI::
0 | 0 | 0 | 0s | 0s | __conn_pid_accessor | DBIx::Class::Storage::DBI::
0 | 0 | 0 | 0s | 0s | __connect_info_accessor | DBIx::Class::Storage::DBI::
0 | 0 | 0 | 0s | 0s | __dbh_accessor | DBIx::Class::Storage::DBI::
0 | 0 | 0 | 0s | 0s | __dbh_autocommit_accessor | DBIx::Class::Storage::DBI::
0 | 0 | 0 | 0s | 0s | __dbh_details_accessor | DBIx::Class::Storage::DBI::
0 | 0 | 0 | 0s | 0s | __dbic_connect_attributes_accessor | DBIx::Class::Storage::DBI::
0 | 0 | 0 | 0s | 0s | __driver_determined_accessor | DBIx::Class::Storage::DBI::
0 | 0 | 0 | 0s | 0s | __perform_autoinc_retrieval_accessor | DBIx::Class::Storage::DBI::
0 | 0 | 0 | 0s | 0s | __sql_maker_accessor | DBIx::Class::Storage::DBI::
0 | 0 | 0 | 0s | 0s | __sql_maker_opts_accessor | DBIx::Class::Storage::DBI::
0 | 0 | 0 | 0s | 0s | _auto_savepoint_accessor | DBIx::Class::Storage::DBI::
0 | 0 | 0 | 0s | 0s | _autoinc_supplied_for_op | DBIx::Class::Storage::DBI::
0 | 0 | 0 | 0s | 0s | _disable_sth_caching_accessor | DBIx::Class::Storage::DBI::
0 | 0 | 0 | 0s | 0s | _on_connect_call_accessor | DBIx::Class::Storage::DBI::
0 | 0 | 0 | 0s | 0s | _on_connect_do_accessor | DBIx::Class::Storage::DBI::
0 | 0 | 0 | 0s | 0s | _on_disconnect_call_accessor | DBIx::Class::Storage::DBI::
0 | 0 | 0 | 0s | 0s | _on_disconnect_do_accessor | DBIx::Class::Storage::DBI::
0 | 0 | 0 | 0s | 0s | _perform_autoinc_retrieval | DBIx::Class::Storage::DBI::
0 | 0 | 0 | 0s | 0s | _unsafe_accessor | DBIx::Class::Storage::DBI::
0 | 0 | 0 | 0s | 0s | auto_savepoint | DBIx::Class::Storage::DBI::
0 | 0 | 0 | 0s | 0s | disable_sth_caching | DBIx::Class::Storage::DBI::
0 | 0 | 0 | 0s | 0s | on_disconnect_call | DBIx::Class::Storage::DBI::
0 | 0 | 0 | 0s | 0s | on_disconnect_do | DBIx::Class::Storage::DBI::
0 | 0 | 0 | 0s | 0s | _auto_savepoint_accessor | DBIx::Class::Storage::
0 | 0 | 0 | 0s | 0s | _debug_accessor | DBIx::Class::Storage::
0 | 0 | 0 | 0s | 0s | _savepoints_accessor | DBIx::Class::Storage::
0 | 0 | 0 | 0s | 0s | _schema_accessor | DBIx::Class::Storage::
0 | 0 | 0 | 0s | 0s | _transaction_depth_accessor | DBIx::Class::Storage::
0 | 0 | 0 | 0s | 0s | auto_savepoint | DBIx::Class::Storage::
0 | 0 | 0 | 0s | 0s | savepoints | DBIx::Class::Storage::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | package Class::Accessor::Grouped; | ||||
2 | 2 | 27µs | # spent 20µs (14+6) within Class::Accessor::Grouped::BEGIN@2 which was called:
# once (14µs+6µs) by base::import at line 2 # spent 20µs making 1 call to Class::Accessor::Grouped::BEGIN@2
# spent 6µs making 1 call to strict::import | ||
3 | 2 | 14µs | # spent 10µs (7+4) within Class::Accessor::Grouped::BEGIN@3 which was called:
# once (7µs+4µs) by base::import at line 3 # spent 10µs making 1 call to Class::Accessor::Grouped::BEGIN@3
# spent 4µs making 1 call to warnings::import | ||
4 | 1 | 4µs | # spent 4µs within Class::Accessor::Grouped::BEGIN@4 which was called:
# once (4µs+0s) by base::import at line 4 # spent 4µs making 1 call to Class::Accessor::Grouped::BEGIN@4 | ||
5 | 1 | 4µs | # spent 4µs within Class::Accessor::Grouped::BEGIN@5 which was called:
# once (4µs+0s) by base::import at line 5 # spent 4µs making 1 call to Class::Accessor::Grouped::BEGIN@5 | ||
6 | 1 | 4µs | # spent 4µs within Class::Accessor::Grouped::BEGIN@6 which was called:
# once (4µs+0s) by base::import at line 6 # spent 4µs making 1 call to Class::Accessor::Grouped::BEGIN@6 | ||
7 | |||||
8 | # spent 4µs within Class::Accessor::Grouped::BEGIN@8 which was called:
# once (4µs+0s) by base::import at line 16 | ||||
9 | # use M::R to work around the 5.8 require bugs | ||||
10 | if ($] < 5.009_005) { | ||||
11 | Module::Runtime::require_module('MRO::Compat'); | ||||
12 | } | ||||
13 | else { | ||||
14 | require mro; | ||||
15 | } | ||||
16 | 1 | 4µs | } # spent 4µs making 1 call to Class::Accessor::Grouped::BEGIN@8 | ||
17 | |||||
18 | our $VERSION = '0.10012'; | ||||
19 | 1 | 3µs | $VERSION = eval $VERSION if $VERSION =~ /_/; # numify for warning-free dev releases # spent 3µs making 1 call to Class::Accessor::Grouped::CORE:match | ||
20 | |||||
21 | # when changing minimum version don't forget to adjust Makefile.PL as well | ||||
22 | our $__minimum_xsa_version; | ||||
23 | 1 | 3µs | # spent 3µs within Class::Accessor::Grouped::BEGIN@23 which was called:
# once (3µs+0s) by base::import at line 23 # spent 3µs making 1 call to Class::Accessor::Grouped::BEGIN@23 | ||
24 | |||||
25 | our $USE_XS; | ||||
26 | # the unless defined is here so that we can override the value | ||||
27 | # before require/use, *regardless* of the state of $ENV{CAG_USE_XS} | ||||
28 | $USE_XS = $ENV{CAG_USE_XS} | ||||
29 | unless defined $USE_XS; | ||||
30 | |||||
31 | # spent 2.09ms (76µs+2.02) within Class::Accessor::Grouped::BEGIN@31 which was called:
# once (76µs+2.02ms) by base::import at line 75 | ||||
32 | package # hide from PAUSE | ||||
33 | __CAG_ENV__; | ||||
34 | |||||
35 | die "Huh?! No minimum C::XSA version?!\n" | ||||
36 | unless $__minimum_xsa_version; | ||||
37 | |||||
38 | local $@; | ||||
39 | require constant; | ||||
40 | |||||
41 | # individual (one const at a time) imports so we are 5.6.2 compatible | ||||
42 | # if we can - why not ;) | ||||
43 | 1 | 55µs | constant->import( NO_SUBNAME => eval { # spent 55µs making 1 call to constant::import | ||
44 | 1 | 44µs | Module::Runtime::require_module('Sub::Name') # spent 44µs making 1 call to Module::Runtime::require_module | ||
45 | } ? 0 : "$@" ); | ||||
46 | |||||
47 | my $found_cxsa; | ||||
48 | 2 | 28µs | constant->import( NO_CXSA => ( NO_SUBNAME() || ( eval { # spent 27µs making 1 call to constant::import
# spent 1µs making 1 call to __CAG_ENV__::__ANON__ | ||
49 | 1 | 1.84ms | Module::Runtime::require_module('Class::XSAccessor'); # spent 1.84ms making 1 call to Module::Runtime::require_module | ||
50 | 1 | 8µs | $found_cxsa = Class::XSAccessor->VERSION; # spent 8µs making 1 call to version::vxs::_VERSION | ||
51 | 1 | 4µs | Class::XSAccessor->VERSION($__minimum_xsa_version); # spent 4µs making 1 call to version::vxs::_VERSION | ||
52 | } ? 0 : "$@" ) ) ); | ||||
53 | |||||
54 | 1 | 600ns | if (NO_CXSA() and $found_cxsa and !$ENV{CAG_OLD_XS_NOWARN}) { # spent 600ns making 1 call to __CAG_ENV__::__ANON__ | ||
55 | warn( | ||||
56 | 'The installed version of Class::XSAccessor is too old ' | ||||
57 | . "(v$found_cxsa < v$__minimum_xsa_version). Please upgrade " | ||||
58 | . "to instantly quadruple the performance of 'simple' accessors. " | ||||
59 | . 'Set $ENV{CAG_OLD_XS_NOWARN} if you wish to disable this ' | ||||
60 | . "warning.\n" | ||||
61 | ); | ||||
62 | } | ||||
63 | |||||
64 | 1 | 15µs | constant->import( BROKEN_GOTO => ($] < '5.008009') ? 1 : 0 ); # spent 15µs making 1 call to constant::import | ||
65 | |||||
66 | 1 | 10µs | constant->import( UNSTABLE_DOLLARAT => ($] < '5.013002') ? 1 : 0 ); # spent 10µs making 1 call to constant::import | ||
67 | |||||
68 | 1 | 10µs | constant->import( TRACK_UNDEFER_FAIL => ( # spent 10µs making 1 call to constant::import | ||
69 | $INC{'Test/Builder.pm'} || $INC{'Test/Builder2.pm'} | ||||
70 | and | ||||
71 | $0 =~ m{ ^ (?: \. \/ )? x?t / .+ \.t $}x | ||||
72 | ) ? 1 : 0 ); | ||||
73 | |||||
74 | # spent 2.35ms within __CAG_ENV__::perlstring which was called 927 times, avg 3µs/call:
# 927 times (2.35ms+0s) by Class::Accessor::Grouped::__ANON__[/usr/share/perl5/Class/Accessor/Grouped.pm:708] at line 700, avg 3µs/call | ||||
75 | 1 | 2.09ms | } # spent 2.09ms making 1 call to Class::Accessor::Grouped::BEGIN@31 | ||
76 | |||||
77 | # Yes this method is undocumented | ||||
78 | # Yes it should be a private coderef like all the rest at the end of this file | ||||
79 | # No we can't do that (yet) because the DBIC-CDBI compat layer overrides it | ||||
80 | # %$*@!?&!&#*$!!! | ||||
81 | |||||
82 | my $illegal_accessors_warned; | ||||
83 | # spent 851ms (111+739) within Class::Accessor::Grouped::_mk_group_accessors which was called 1920 times, avg 443µs/call:
# 1920 times (111ms+739ms) by Class::Accessor::Grouped::mk_group_accessors at line 251, avg 443µs/call | ||||
84 | my($self, $maker, $group, @fields) = @_; | ||||
85 | my $class = length (ref ($self) ) ? ref ($self) : $self; | ||||
86 | |||||
87 | 2 | 24µs | # spent 17µs (10+7) within Class::Accessor::Grouped::BEGIN@87 which was called:
# once (10µs+7µs) by base::import at line 87 # spent 17µs making 1 call to Class::Accessor::Grouped::BEGIN@87
# spent 7µs making 1 call to strict::unimport | ||
88 | 2 | 27µs | # spent 17µs (8+10) within Class::Accessor::Grouped::BEGIN@88 which was called:
# once (8µs+10µs) by base::import at line 88 # spent 17µs making 1 call to Class::Accessor::Grouped::BEGIN@88
# spent 10µs making 1 call to warnings::unimport | ||
89 | |||||
90 | # So we don't have to do lots of lookups inside the loop. | ||||
91 | 1920 | 10.2ms | $maker = $self->can($maker) unless ref $maker; # spent 10.2ms making 1920 calls to UNIVERSAL::can, avg 5µs/call | ||
92 | |||||
93 | for (@fields) { | ||||
94 | |||||
95 | my ($name, $field) = (ref $_) ? (@$_) : ($_, $_); | ||||
96 | |||||
97 | 1966 | 4.89ms | if ($name !~ /\A[A-Z_a-z][0-9A-Z_a-z]*\z/) { # spent 4.89ms making 1966 calls to Class::Accessor::Grouped::CORE:match, avg 2µs/call | ||
98 | |||||
99 | if ($name =~ /\0/) { | ||||
100 | Carp::croak(sprintf | ||||
101 | "Illegal accessor name %s - nulls should never appear in stash keys", | ||||
102 | __CAG_ENV__::perlstring($name), | ||||
103 | ); | ||||
104 | } | ||||
105 | elsif (! $ENV{CAG_ILLEGAL_ACCESSOR_NAME_OK} ) { | ||||
106 | Carp::croak( | ||||
107 | "Illegal accessor name '$name'. If you want CAG to attempt creating " | ||||
108 | . 'it anyway (possible if Sub::Name is available) set ' | ||||
109 | . '$ENV{CAG_ILLEGAL_ACCESSOR_NAME_OK}' | ||||
110 | ); | ||||
111 | } | ||||
112 | elsif (__CAG_ENV__::NO_SUBNAME) { | ||||
113 | Carp::croak( | ||||
114 | "Unable to install accessor with illegal name '$name': " | ||||
115 | . 'Sub::Name not available' | ||||
116 | ); | ||||
117 | } | ||||
118 | elsif ( | ||||
119 | # Because one of the former maintainers of DBIC::SL is a raging | ||||
120 | # idiot, there is now a ton of DBIC code out there that attempts | ||||
121 | # to create column accessors with illegal names. In the interest | ||||
122 | # of not cluttering the logs of unsuspecting victims (unsuspecting | ||||
123 | # because these accessors are unusable anyway) we provide an | ||||
124 | # explicit "do not warn at all" escape, until all such code is | ||||
125 | # fixed (this will be a loooooong time >:( | ||||
126 | $ENV{CAG_ILLEGAL_ACCESSOR_NAME_OK} ne 'DO_NOT_WARN' | ||||
127 | and | ||||
128 | ! $illegal_accessors_warned->{$class}++ | ||||
129 | ) { | ||||
130 | Carp::carp( | ||||
131 | "Installing illegal accessor '$name' into $class, see " | ||||
132 | . 'documentation for more details' | ||||
133 | ); | ||||
134 | } | ||||
135 | } | ||||
136 | |||||
137 | 1966 | 1.26ms | Carp::carp("Having a data accessor named '$name' in '$class' is unwise.") # spent 1.26ms making 1966 calls to Class::Accessor::Grouped::CORE:match, avg 641ns/call | ||
138 | if $name =~ /\A(?: DESTROY | AUTOLOAD | CLONE )\z/x; | ||||
139 | |||||
140 | my $alias = "_${name}_accessor"; | ||||
141 | |||||
142 | for ($name, $alias) { | ||||
143 | |||||
144 | # the maker may elect to not return anything, meaning it already | ||||
145 | # installed the coderef for us (e.g. lack of Sub::Name) | ||||
146 | 3932 | 703ms | my $cref = $self->$maker($group, $field, $_) # spent 703ms making 3932 calls to Class::Accessor::Grouped::make_group_accessor, avg 179µs/call | ||
147 | or next; | ||||
148 | |||||
149 | my $fq_meth = "${class}::$_"; | ||||
150 | |||||
151 | 3932 | 20.3ms | *$fq_meth = Sub::Name::subname($fq_meth, $cref); # spent 20.3ms making 3932 calls to Sub::Name::subname, avg 5µs/call | ||
152 | #unless defined &{$class."\:\:$field"} | ||||
153 | } | ||||
154 | } | ||||
155 | }; | ||||
156 | |||||
157 | # $gen_accessor coderef is setup at the end for clarity | ||||
158 | my $gen_accessor; | ||||
159 | |||||
160 | =head1 NAME | ||||
161 | |||||
162 | Class::Accessor::Grouped - Lets you build groups of accessors | ||||
163 | |||||
164 | =head1 SYNOPSIS | ||||
165 | |||||
166 | use base 'Class::Accessor::Grouped'; | ||||
167 | |||||
168 | # make basic accessors for objects | ||||
169 | __PACKAGE__->mk_group_accessors(simple => qw(id name email)); | ||||
170 | |||||
171 | # make accessor that works for objects and classes | ||||
172 | __PACKAGE__->mk_group_accessors(inherited => 'awesome_level'); | ||||
173 | |||||
174 | # make an accessor which calls a custom pair of getters/setters | ||||
175 | sub get_column { ... this will be called when you do $obj->name() ... } | ||||
176 | sub set_column { ... this will be called when you do $obj->name('foo') ... } | ||||
177 | __PACKAGE__->mk_group_accessors(column => 'name'); | ||||
178 | |||||
179 | =head1 DESCRIPTION | ||||
180 | |||||
181 | This class lets you build groups of accessors that will call different | ||||
182 | getters and setters. The documentation of this module still requires a lot | ||||
183 | of work (B<< volunteers welcome >.> >>), but in the meantime you can refer to | ||||
184 | L<this post|http://lo-f.at/glahn/2009/08/WritingPowerfulAccessorsForPerlClasses.html> | ||||
185 | for more information. | ||||
186 | |||||
187 | =head2 Notes on accessor names | ||||
188 | |||||
189 | In general method names in Perl are considered identifiers, and as such need to | ||||
190 | conform to the identifier specification of C<qr/\A[A-Z_a-z][0-9A-Z_a-z]*\z/>. | ||||
191 | While it is rather easy to invoke methods with non-standard names | ||||
192 | (C<< $obj->${\"anything goes"} >>), it is not possible to properly declare such | ||||
193 | methods without the use of L<Sub::Name>. Since this module must be able to | ||||
194 | function identically with and without its optional dependencies, starting with | ||||
195 | version C<0.10008> attempting to declare an accessor with a non-standard name | ||||
196 | is a fatal error (such operations would silently succeed since version | ||||
197 | C<0.08004>, as long as L<Sub::Name> is present, or otherwise would result in a | ||||
198 | syntax error during a string eval). | ||||
199 | |||||
200 | Unfortunately in the years since C<0.08004> a rather large body of code | ||||
201 | accumulated in the wild that does attempt to declare accessors with funny | ||||
202 | names. One notable perpetrator is L<DBIx::Class::Schema::Loader>, which under | ||||
203 | certain conditions could create accessors of the C<column> group which start | ||||
204 | with numbers and/or some other punctuation (the proper way would be to declare | ||||
205 | columns with the C<accessor> attribute set to C<undef>). | ||||
206 | |||||
207 | Therefore an escape mechanism is provided via the environment variable | ||||
208 | C<CAG_ILLEGAL_ACCESSOR_NAME_OK>. When set to a true value, one warning is | ||||
209 | issued B<per class> on attempts to declare an accessor with a non-conforming | ||||
210 | name, and as long as L<Sub::Name> is available all accessors will be properly | ||||
211 | created. Regardless of this setting, accessor names containing nulls C<"\0"> | ||||
212 | are disallowed, due to various deficiencies in perl itself. | ||||
213 | |||||
214 | If your code base has too many instances of illegal accessor declarations, and | ||||
215 | a fix is not feasible due to time constraints, it is possible to disable the | ||||
216 | warnings altogether by setting C<$ENV{CAG_ILLEGAL_ACCESSOR_NAME_OK}> to | ||||
217 | C<DO_NOT_WARN> (observe capitalization). | ||||
218 | |||||
219 | =head1 METHODS | ||||
220 | |||||
221 | =head2 mk_group_accessors | ||||
222 | |||||
223 | __PACKAGE__->mk_group_accessors(simple => 'hair_length', [ hair_color => 'hc' ]); | ||||
224 | |||||
225 | =over 4 | ||||
226 | |||||
227 | =item Arguments: $group, @fieldspec | ||||
228 | |||||
229 | Returns: none | ||||
230 | |||||
231 | =back | ||||
232 | |||||
233 | Creates a set of accessors in a given group. | ||||
234 | |||||
235 | $group is the name of the accessor group for the generated accessors; they | ||||
236 | will call get_$group($field) on get and set_$group($field, $value) on set. | ||||
237 | |||||
238 | If you want to mimic Class::Accessor's mk_accessors $group has to be 'simple' | ||||
239 | to tell Class::Accessor::Grouped to use its own get_simple and set_simple | ||||
240 | methods. | ||||
241 | |||||
242 | @fieldspec is a list of field/accessor names; if a fieldspec is a scalar | ||||
243 | this is used as both field and accessor name, if a listref it is expected to | ||||
244 | be of the form [ $accessor, $field ]. | ||||
245 | |||||
246 | =cut | ||||
247 | |||||
248 | # spent 874ms (23.7+851) within Class::Accessor::Grouped::mk_group_accessors which was called 1920 times, avg 455µs/call:
# 1599 times (20.5ms+751ms) by DBIx::Class::Row::register_column at line 1454 of DBIx/Class/Row.pm, avg 482µs/call
# 184 times (2.32ms+19.2ms) by DBIx::Class::mk_classaccessor at line 36 of DBIx/Class.pm, avg 117µs/call
# 122 times (729µs+51.4ms) by DBIx::Class::InflateColumn::inflate_column at line 101 of DBIx/Class/InflateColumn.pm, avg 427µs/call
# once (6µs+15.5ms) by Class::C3::Componentised::ensure_class_loaded at line 73 of DBIx/Class/Storage/DBI.pm
# once (13µs+4.53ms) by Class::C3::Componentised::ensure_class_loaded at line 74 of DBIx/Class/Storage/DBI.pm
# once (14µs+2.72ms) by Class::C3::Componentised::ensure_class_loaded at line 22 of DBIx/Class/Storage/DBI.pm
# once (10µs+1.51ms) by Class::C3::Componentised::ensure_class_loaded at line 26 of DBIx/Class/Storage/DBI.pm
# once (5µs+1.16ms) by base::import at line 23 of DBIx/Class/Storage.pm
# once (4µs+645µs) by Class::C3::Componentised::ensure_class_loaded at line 28 of DBIx/Class/ResultSource.pm
# once (11µs+569µs) by Class::C3::Componentised::ensure_class_loaded at line 33 of DBIx/Class/Storage/DBI.pm
# once (14µs+507µs) by Class::C3::Componentised::ensure_class_loaded at line 21 of DBIx/Class/ResultSource.pm
# once (14µs+466µs) by base::import at line 13 of DBIx/Class/ResultSourceProxy.pm
# once (14µs+358µs) by base::import at line 22 of DBIx/Class/Storage.pm
# once (11µs+328µs) by base::import at line 27 of DBIx/Class.pm
# once (4µs+328µs) by Class::C3::Componentised::ensure_class_loaded at line 45 of DBIx/Class/Storage/DBI.pm
# once (12µs+249µs) by base::import at line 27 of DBIx/Class/Row.pm
# once (10µs+183µs) by DBIx::Class::ResultSource::BEGIN@9 at line 15 of DBIx/Class/ResultSourceHandle.pm
# once (12µs+153µs) by DBIx::Class::ResultSource::Table::BEGIN@6 at line 34 of DBIx/Class/ResultSet.pm | ||||
249 | my ($self, $group, @fields) = @_; | ||||
250 | |||||
251 | 1920 | 851ms | $self->_mk_group_accessors('make_group_accessor', $group, @fields); # spent 851ms making 1920 calls to Class::Accessor::Grouped::_mk_group_accessors, avg 443µs/call | ||
252 | return; | ||||
253 | } | ||||
254 | |||||
255 | =head2 mk_group_ro_accessors | ||||
256 | |||||
257 | __PACKAGE__->mk_group_ro_accessors(simple => 'birthdate', [ social_security_number => 'ssn' ]); | ||||
258 | |||||
259 | =over 4 | ||||
260 | |||||
261 | =item Arguments: $group, @fieldspec | ||||
262 | |||||
263 | Returns: none | ||||
264 | |||||
265 | =back | ||||
266 | |||||
267 | Creates a set of read only accessors in a given group. Identical to | ||||
268 | L</mk_group_accessors> but accessors will throw an error if passed a value | ||||
269 | rather than setting the value. | ||||
270 | |||||
271 | =cut | ||||
272 | |||||
273 | sub mk_group_ro_accessors { | ||||
274 | my($self, $group, @fields) = @_; | ||||
275 | |||||
276 | $self->_mk_group_accessors('make_group_ro_accessor', $group, @fields); | ||||
277 | return; | ||||
278 | } | ||||
279 | |||||
280 | =head2 mk_group_wo_accessors | ||||
281 | |||||
282 | __PACKAGE__->mk_group_wo_accessors(simple => 'lie', [ subject => 'subj' ]); | ||||
283 | |||||
284 | =over 4 | ||||
285 | |||||
286 | =item Arguments: $group, @fieldspec | ||||
287 | |||||
288 | Returns: none | ||||
289 | |||||
290 | =back | ||||
291 | |||||
292 | Creates a set of write only accessors in a given group. Identical to | ||||
293 | L</mk_group_accessors> but accessors will throw an error if not passed a | ||||
294 | value rather than getting the value. | ||||
295 | |||||
296 | =cut | ||||
297 | |||||
298 | sub mk_group_wo_accessors { | ||||
299 | my($self, $group, @fields) = @_; | ||||
300 | |||||
301 | $self->_mk_group_accessors('make_group_wo_accessor', $group, @fields); | ||||
302 | return; | ||||
303 | } | ||||
304 | |||||
305 | =head2 get_simple | ||||
306 | |||||
307 | =over 4 | ||||
308 | |||||
309 | =item Arguments: $field | ||||
310 | |||||
311 | Returns: $value | ||||
312 | |||||
313 | =back | ||||
314 | |||||
315 | Simple getter for hash-based objects which returns the value for the field | ||||
316 | name passed as an argument. | ||||
317 | |||||
318 | =cut | ||||
319 | |||||
320 | sub get_simple { | ||||
321 | $_[0]->{$_[1]}; | ||||
322 | } | ||||
323 | |||||
324 | =head2 set_simple | ||||
325 | |||||
326 | =over 4 | ||||
327 | |||||
328 | =item Arguments: $field, $new_value | ||||
329 | |||||
330 | Returns: $new_value | ||||
331 | |||||
332 | =back | ||||
333 | |||||
334 | Simple setter for hash-based objects which sets and then returns the value | ||||
335 | for the field name passed as an argument. | ||||
336 | |||||
337 | =cut | ||||
338 | |||||
339 | sub set_simple { | ||||
340 | $_[0]->{$_[1]} = $_[2]; | ||||
341 | } | ||||
342 | |||||
343 | |||||
344 | =head2 get_inherited | ||||
345 | |||||
346 | =over 4 | ||||
347 | |||||
348 | =item Arguments: $field | ||||
349 | |||||
350 | Returns: $value | ||||
351 | |||||
352 | =back | ||||
353 | |||||
354 | Simple getter for Classes and hash-based objects which returns the value for | ||||
355 | the field name passed as an argument. This behaves much like | ||||
356 | L<Class::Data::Accessor> where the field can be set in a base class, | ||||
357 | inherited and changed in subclasses, and inherited and changed for object | ||||
358 | instances. | ||||
359 | |||||
360 | =cut | ||||
361 | |||||
362 | # spent 24.3ms (21.4+2.86) within Class::Accessor::Grouped::get_inherited which was called 3450 times, avg 7µs/call:
# 3093 times (20.0ms+2.54ms) by DBIx::Class::ResultSourceProxy::Table::table_class or DBIx::Class::Schema::class_mappings or DBIx::Class::Schema::default_resultset_attributes or DBIx::Class::Schema::source_registrations or DBIx::Class::Schema::storage or DBIx::Class::Schema::storage_type or Koha::Objects::search or Koha::Schema::Result::Accountline::result_source_instance or Koha::Schema::Result::Accountoffset::result_source_instance or Koha::Schema::Result::ActionLog::result_source_instance or Koha::Schema::Result::ActionLogs::result_source_instance or Koha::Schema::Result::AdditionalField::result_source_instance or Koha::Schema::Result::AdditionalFieldValue::result_source_instance or Koha::Schema::Result::Alert::result_source_instance or Koha::Schema::Result::Aqbasket::result_source_instance or Koha::Schema::Result::Aqbasketgroup::result_source_instance or Koha::Schema::Result::Aqbasketuser::result_source_instance or Koha::Schema::Result::Aqbookseller::result_source_instance or Koha::Schema::Result::Aqbudget::result_source_instance or Koha::Schema::Result::Aqbudgetborrower::result_source_instance or Koha::Schema::Result::Aqbudgetperiod::result_source_instance or Koha::Schema::Result::AqbudgetsPlanning::result_source_instance or Koha::Schema::Result::Aqcontact::result_source_instance or Koha::Schema::Result::Aqcontract::result_source_instance or Koha::Schema::Result::Aqinvoice::result_source_instance or Koha::Schema::Result::Aqorder::result_source_instance or Koha::Schema::Result::AqorderUser::result_source_instance or Koha::Schema::Result::AqordersItem::result_source_instance or Koha::Schema::Result::AqordersTransfer::result_source_instance or Koha::Schema::Result::AudioAlert::result_source_instance or Koha::Schema::Result::AuthHeader::result_source_instance or Koha::Schema::Result::AuthSubfieldStructure::result_source_instance or Koha::Schema::Result::AuthTagStructure::result_source_instance or Koha::Schema::Result::AuthType::result_source_instance or Koha::Schema::Result::AuthorisedValue::result_source_instance or Koha::Schema::Result::AuthorisedValuesBranch::result_source_instance or Koha::Schema::Result::Biblio::result_source_instance or Koha::Schema::Result::BiblioFramework::result_source_instance or Koha::Schema::Result::Biblioimage::result_source_instance or Koha::Schema::Result::Biblioitem::result_source_instance or Koha::Schema::Result::Borrower::result_source_instance or Koha::Schema::Result::BorrowerAttribute::result_source_instance or Koha::Schema::Result::BorrowerAttributeType::result_source_instance or Koha::Schema::Result::BorrowerAttributeTypesBranch::result_source_instance or Koha::Schema::Result::BorrowerDebarment::result_source_instance or Koha::Schema::Result::BorrowerFile::result_source_instance or Koha::Schema::Result::BorrowerMessagePreference::result_source_instance or Koha::Schema::Result::BorrowerMessageTransportPreference::result_source_instance or Koha::Schema::Result::BorrowerModification::result_source_instance or Koha::Schema::Result::BorrowerSync::result_source_instance or Koha::Schema::Result::Branch::result_source_instance or Koha::Schema::Result::BranchBorrowerCircRule::result_source_instance or Koha::Schema::Result::BranchItemRule::result_source_instance or Koha::Schema::Result::BranchTransferLimit::result_source_instance or Koha::Schema::Result::Branchcategory::result_source_instance or Koha::Schema::Result::Branchrelation::result_source_instance or Koha::Schema::Result::Branchtransfer::result_source_instance or Koha::Schema::Result::Browser::result_source_instance or Koha::Schema::Result::CategoriesBranch::result_source_instance or Koha::Schema::Result::Category::result_source_instance or Koha::Schema::Result::City::result_source_instance or Koha::Schema::Result::ClassSortRule::result_source_instance or Koha::Schema::Result::ClassSource::result_source_instance or Koha::Schema::Result::Collection::result_source_instance or Koha::Schema::Result::CollectionsTracking::result_source_instance or Koha::Schema::Result::ColumnsSetting::result_source_instance or Koha::Schema::Result::Course::result_source_instance or Koha::Schema::Result::CourseInstructor::result_source_instance or Koha::Schema::Result::CourseItem::result_source_instance or Koha::Schema::Result::CourseReserve::result_source_instance or Koha::Schema::Result::CreatorBatch::result_source_instance or Koha::Schema::Result::CreatorImage::result_source_instance or Koha::Schema::Result::CreatorLayout::result_source_instance or Koha::Schema::Result::CreatorTemplate::result_source_instance or Koha::Schema::Result::Currency::result_source_instance or Koha::Schema::Result::DefaultBorrowerCircRule::result_source_instance or Koha::Schema::Result::DefaultBranchCircRule::result_source_instance or Koha::Schema::Result::DefaultBranchItemRule::result_source_instance or Koha::Schema::Result::DefaultCircRule::result_source_instance or Koha::Schema::Result::Deletedbiblio::result_source_instance or Koha::Schema::Result::Deletedbiblioitem::result_source_instance or Koha::Schema::Result::Deletedborrower::result_source_instance or Koha::Schema::Result::Deleteditem::result_source_instance or Koha::Schema::Result::Discharge::result_source_instance or Koha::Schema::Result::ExportFormat::result_source_instance or Koha::Schema::Result::Fieldmapping::result_source_instance or Koha::Schema::Result::HoldFillTarget::result_source_instance or Koha::Schema::Result::ImportAuth::result_source_instance or Koha::Schema::Result::ImportBatch::result_source_instance or Koha::Schema::Result::ImportBiblio::result_source_instance or Koha::Schema::Result::ImportItem::result_source_instance or Koha::Schema::Result::ImportRecord::result_source_instance or Koha::Schema::Result::ImportRecordMatch::result_source_instance or Koha::Schema::Result::Issue::result_source_instance or Koha::Schema::Result::Issuingrule::result_source_instance or Koha::Schema::Result::Item::result_source_instance or Koha::Schema::Result::ItemCirculationAlertPreference::result_source_instance or Koha::Schema::Result::ItemsLastBorrower::result_source_instance or Koha::Schema::Result::ItemsSearchField::result_source_instance or Koha::Schema::Result::Itemtype::result_source_instance or Koha::Schema::Result::LanguageDescription::result_source_instance or Koha::Schema::Result::LanguageRfc4646ToIso639::result_source_instance or Koha::Schema::Result::LanguageScriptBidi::result_source_instance or Koha::Schema::Result::LanguageScriptMapping::result_source_instance or Koha::Schema::Result::LanguageSubtagRegistry::result_source_instance or Koha::Schema::Result::Letter::result_source_instance or Koha::Schema::Result::Linktracker::result_source_instance or Koha::Schema::Result::Localization::result_source_instance or Koha::Schema::Result::MarcMatcher::result_source_instance or Koha::Schema::Result::MarcModificationTemplate::result_source_instance or Koha::Schema::Result::MarcModificationTemplateAction::result_source_instance or Koha::Schema::Result::MarcSubfieldStructure::result_source_instance or Koha::Schema::Result::MarcTagStructure::result_source_instance or Koha::Schema::Result::Matchcheck::result_source_instance or Koha::Schema::Result::MatcherMatchpoint::result_source_instance or Koha::Schema::Result::Matchpoint::result_source_instance or Koha::Schema::Result::MatchpointComponent::result_source_instance or Koha::Schema::Result::MatchpointComponentNorm::result_source_instance or Koha::Schema::Result::Message::result_source_instance or Koha::Schema::Result::MessageAttribute::result_source_instance or Koha::Schema::Result::MessageQueue::result_source_instance or Koha::Schema::Result::MessageTransport::result_source_instance or Koha::Schema::Result::MessageTransportType::result_source_instance or Koha::Schema::Result::MiscFile::result_source_instance or Koha::Schema::Result::NeedMergeAuthority::result_source_instance or Koha::Schema::Result::Notify::result_source_instance or Koha::Schema::Result::OaiSet::result_source_instance or Koha::Schema::Result::OaiSetsBiblio::result_source_instance or Koha::Schema::Result::OaiSetsDescription::result_source_instance or Koha::Schema::Result::OaiSetsMapping::result_source_instance or Koha::Schema::Result::OldIssue::result_source_instance or Koha::Schema::Result::OldReserve::result_source_instance or Koha::Schema::Result::OpacNews::result_source_instance or Koha::Schema::Result::Overduerule::result_source_instance or Koha::Schema::Result::OverduerulesTransportType::result_source_instance or Koha::Schema::Result::PatronList::result_source_instance or Koha::Schema::Result::PatronListPatron::result_source_instance or Koha::Schema::Result::Patronimage::result_source_instance or Koha::Schema::Result::PendingOfflineOperation::result_source_instance or Koha::Schema::Result::Permission::result_source_instance or Koha::Schema::Result::PluginData::result_source_instance or Koha::Schema::Result::Printer::result_source_instance or Koha::Schema::Result::PrintersProfile::result_source_instance or Koha::Schema::Result::Quote::result_source_instance or Koha::Schema::Result::Rating::result_source_instance or Koha::Schema::Result::RepeatableHoliday::result_source_instance or Koha::Schema::Result::ReportsDictionary::result_source_instance or Koha::Schema::Result::Reserve::result_source_instance or Koha::Schema::Result::Review::result_source_instance or Koha::Schema::Result::SavedReport::result_source_instance or Koha::Schema::Result::SavedSql::result_source_instance or Koha::Schema::Result::SearchHistory::result_source_instance or Koha::Schema::Result::Serial::result_source_instance or Koha::Schema::Result::Serialitem::result_source_instance or Koha::Schema::Result::ServicesThrottle::result_source_instance or Koha::Schema::Result::Session::result_source_instance or Koha::Schema::Result::SocialData::result_source_instance or Koha::Schema::Result::SpecialHoliday::result_source_instance or Koha::Schema::Result::Statistic::result_source_instance or Koha::Schema::Result::Stopword::result_source_instance or Koha::Schema::Result::Subscription::result_source_instance or Koha::Schema::Result::SubscriptionFrequency::result_source_instance or Koha::Schema::Result::SubscriptionNumberpattern::result_source_instance or Koha::Schema::Result::Subscriptionhistory::result_source_instance or Koha::Schema::Result::Subscriptionroutinglist::result_source_instance or Koha::Schema::Result::Suggestion::result_source_instance or Koha::Schema::Result::Systempreference::result_source_instance or Koha::Schema::Result::Tag::result_source_instance or Koha::Schema::Result::TagAll::result_source_instance or Koha::Schema::Result::TagsApproval::result_source_instance or Koha::Schema::Result::TagsIndex::result_source_instance or Koha::Schema::Result::TmpHoldsqueue::result_source_instance or Koha::Schema::Result::TransportCost::result_source_instance or Koha::Schema::Result::UploadedFile::result_source_instance or Koha::Schema::Result::UserPermission::result_source_instance or Koha::Schema::Result::Userflag::result_source_instance or Koha::Schema::Result::Virtualshelfcontent::result_source_instance or Koha::Schema::Result::Virtualshelfshare::result_source_instance or Koha::Schema::Result::Virtualshelve::result_source_instance or Koha::Schema::Result::Z3950server::result_source_instance or Koha::Schema::Result::Zebraqueue::result_source_instance at line 2 of (eval 167)[Class/Accessor/Grouped.pm:764], avg 7µs/call
# 357 times (1.42ms+315µs) by DBIx::Class::AccessorGroup::get_component_class at line 13 of DBIx/Class/AccessorGroup.pm, avg 5µs/call | ||||
363 | 5 | 6µs | if ( length (ref ($_[0]) ) ) { | ||
364 | 5 | 23µs | 540 | 430µs | if (Scalar::Util::reftype $_[0] eq 'HASH') { # spent 430µs making 540 calls to Scalar::Util::reftype, avg 797ns/call |
365 | 5 | 20µs | return $_[0]->{$_[1]} if exists $_[0]->{$_[1]}; | ||
366 | # everything in @_ is aliased, an assignment won't work | ||||
367 | 1 | 3µs | splice @_, 0, 1, ref($_[0]); | ||
368 | } | ||||
369 | else { | ||||
370 | Carp::croak('Cannot get inherited value on an object instance that is not hash-based'); | ||||
371 | } | ||||
372 | } | ||||
373 | |||||
374 | # if we got this far there is nothing in the instance | ||||
375 | # OR this is a class call | ||||
376 | # in any case $_[0] contains the class name (see splice above) | ||||
377 | 2 | 26µs | # spent 18µs (11+7) within Class::Accessor::Grouped::BEGIN@377 which was called:
# once (11µs+7µs) by base::import at line 377 # spent 18µs making 1 call to Class::Accessor::Grouped::BEGIN@377
# spent 7µs making 1 call to strict::unimport | ||
378 | 2 | 29µs | # spent 19µs (8+10) within Class::Accessor::Grouped::BEGIN@378 which was called:
# once (8µs+10µs) by base::import at line 378 # spent 19µs making 1 call to Class::Accessor::Grouped::BEGIN@378
# spent 10µs making 1 call to warnings::unimport | ||
379 | |||||
380 | 1 | 2µs | my $cag_slot = '::__cag_'. $_[1]; | ||
381 | 1 | 10µs | return ${$_[0].$cag_slot} if defined(${$_[0].$cag_slot}); | ||
382 | |||||
383 | do { return ${$_.$cag_slot} if defined(${$_.$cag_slot}) } | ||||
384 | 1 | 18µs | 182 | 2.43ms | for $_[0]->get_super_paths; # spent 2.43ms making 182 calls to Class::Accessor::Grouped::get_super_paths, avg 13µs/call |
385 | |||||
386 | return undef; | ||||
387 | } | ||||
388 | |||||
389 | =head2 set_inherited | ||||
390 | |||||
391 | =over 4 | ||||
392 | |||||
393 | =item Arguments: $field, $new_value | ||||
394 | |||||
395 | Returns: $new_value | ||||
396 | |||||
397 | =back | ||||
398 | |||||
399 | Simple setter for Classes and hash-based objects which sets and then returns | ||||
400 | the value for the field name passed as an argument. When called on a hash-based | ||||
401 | object it will set the appropriate hash key value. When called on a class, it | ||||
402 | will set a class level variable. | ||||
403 | |||||
404 | B<Note:>: This method will die if you try to set an object variable on a non | ||||
405 | hash-based object. | ||||
406 | |||||
407 | =cut | ||||
408 | |||||
409 | # spent 2.56ms (2.44+124µs) within Class::Accessor::Grouped::set_inherited which was called 720 times, avg 4µs/call:
# 706 times (2.35ms+124µs) by DBIx::Class::Schema::class_mappings or DBIx::Class::Schema::source_registrations or DBIx::Class::Schema::storage or DBIx::Class::Storage::DBI::sql_limit_dialect or DBIx::Class::Storage::DBI::sql_name_sep or DBIx::Class::Storage::DBI::sql_quote_char or DBIx::Class::_skip_namespace_frames or Koha::Schema::Result::Accountline::result_source_instance or Koha::Schema::Result::Accountoffset::result_source_instance or Koha::Schema::Result::ActionLog::result_source_instance or Koha::Schema::Result::ActionLogs::result_source_instance or Koha::Schema::Result::AdditionalField::result_source_instance or Koha::Schema::Result::AdditionalFieldValue::result_source_instance or Koha::Schema::Result::Alert::result_source_instance or Koha::Schema::Result::Aqbasket::result_source_instance or Koha::Schema::Result::Aqbasketgroup::result_source_instance or Koha::Schema::Result::Aqbasketuser::result_source_instance or Koha::Schema::Result::Aqbookseller::result_source_instance or Koha::Schema::Result::Aqbudget::result_source_instance or Koha::Schema::Result::Aqbudgetborrower::result_source_instance or Koha::Schema::Result::Aqbudgetperiod::result_source_instance or Koha::Schema::Result::AqbudgetsPlanning::result_source_instance or Koha::Schema::Result::Aqcontact::result_source_instance or Koha::Schema::Result::Aqcontract::result_source_instance or Koha::Schema::Result::Aqinvoice::result_source_instance or Koha::Schema::Result::Aqorder::result_source_instance or Koha::Schema::Result::AqorderUser::result_source_instance or Koha::Schema::Result::AqordersItem::result_source_instance or Koha::Schema::Result::AqordersTransfer::result_source_instance or Koha::Schema::Result::AudioAlert::result_source_instance or Koha::Schema::Result::AuthHeader::result_source_instance or Koha::Schema::Result::AuthSubfieldStructure::result_source_instance or Koha::Schema::Result::AuthTagStructure::result_source_instance or Koha::Schema::Result::AuthType::result_source_instance or Koha::Schema::Result::AuthorisedValue::result_source_instance or Koha::Schema::Result::AuthorisedValuesBranch::result_source_instance or Koha::Schema::Result::Biblio::result_source_instance or Koha::Schema::Result::BiblioFramework::result_source_instance or Koha::Schema::Result::Biblioimage::result_source_instance or Koha::Schema::Result::Biblioitem::result_source_instance or Koha::Schema::Result::Borrower::result_source_instance or Koha::Schema::Result::BorrowerAttribute::result_source_instance or Koha::Schema::Result::BorrowerAttributeType::result_source_instance or Koha::Schema::Result::BorrowerAttributeTypesBranch::result_source_instance or Koha::Schema::Result::BorrowerDebarment::result_source_instance or Koha::Schema::Result::BorrowerFile::result_source_instance or Koha::Schema::Result::BorrowerMessagePreference::result_source_instance or Koha::Schema::Result::BorrowerMessageTransportPreference::result_source_instance or Koha::Schema::Result::BorrowerModification::result_source_instance or Koha::Schema::Result::BorrowerSync::result_source_instance or Koha::Schema::Result::Branch::result_source_instance or Koha::Schema::Result::BranchBorrowerCircRule::result_source_instance or Koha::Schema::Result::BranchItemRule::result_source_instance or Koha::Schema::Result::BranchTransferLimit::result_source_instance or Koha::Schema::Result::Branchcategory::result_source_instance or Koha::Schema::Result::Branchrelation::result_source_instance or Koha::Schema::Result::Branchtransfer::result_source_instance or Koha::Schema::Result::Browser::result_source_instance or Koha::Schema::Result::CategoriesBranch::result_source_instance or Koha::Schema::Result::Category::result_source_instance or Koha::Schema::Result::City::result_source_instance or Koha::Schema::Result::ClassSortRule::result_source_instance or Koha::Schema::Result::ClassSource::result_source_instance or Koha::Schema::Result::Collection::result_source_instance or Koha::Schema::Result::CollectionsTracking::result_source_instance or Koha::Schema::Result::ColumnsSetting::result_source_instance or Koha::Schema::Result::Course::result_source_instance or Koha::Schema::Result::CourseInstructor::result_source_instance or Koha::Schema::Result::CourseItem::result_source_instance or Koha::Schema::Result::CourseReserve::result_source_instance or Koha::Schema::Result::CreatorBatch::result_source_instance or Koha::Schema::Result::CreatorImage::result_source_instance or Koha::Schema::Result::CreatorLayout::result_source_instance or Koha::Schema::Result::CreatorTemplate::result_source_instance or Koha::Schema::Result::Currency::result_source_instance or Koha::Schema::Result::DefaultBorrowerCircRule::result_source_instance or Koha::Schema::Result::DefaultBranchCircRule::result_source_instance or Koha::Schema::Result::DefaultBranchItemRule::result_source_instance or Koha::Schema::Result::DefaultCircRule::result_source_instance or Koha::Schema::Result::Deletedbiblio::result_source_instance or Koha::Schema::Result::Deletedbiblioitem::result_source_instance or Koha::Schema::Result::Deletedborrower::result_source_instance or Koha::Schema::Result::Deleteditem::result_source_instance or Koha::Schema::Result::Discharge::result_source_instance or Koha::Schema::Result::ExportFormat::result_source_instance or Koha::Schema::Result::Fieldmapping::result_source_instance or Koha::Schema::Result::HoldFillTarget::result_source_instance or Koha::Schema::Result::ImportAuth::result_source_instance or Koha::Schema::Result::ImportBatch::result_source_instance or Koha::Schema::Result::ImportBiblio::result_source_instance or Koha::Schema::Result::ImportItem::result_source_instance or Koha::Schema::Result::ImportRecord::result_source_instance or Koha::Schema::Result::ImportRecordMatch::result_source_instance or Koha::Schema::Result::Issue::result_source_instance or Koha::Schema::Result::Issuingrule::result_source_instance or Koha::Schema::Result::Item::result_source_instance or Koha::Schema::Result::ItemCirculationAlertPreference::result_source_instance or Koha::Schema::Result::ItemsLastBorrower::result_source_instance or Koha::Schema::Result::ItemsSearchField::result_source_instance or Koha::Schema::Result::Itemtype::result_source_instance or Koha::Schema::Result::LanguageDescription::result_source_instance or Koha::Schema::Result::LanguageRfc4646ToIso639::result_source_instance or Koha::Schema::Result::LanguageScriptBidi::result_source_instance or Koha::Schema::Result::LanguageScriptMapping::result_source_instance or Koha::Schema::Result::LanguageSubtagRegistry::result_source_instance or Koha::Schema::Result::Letter::result_source_instance or Koha::Schema::Result::Linktracker::result_source_instance or Koha::Schema::Result::Localization::result_source_instance or Koha::Schema::Result::MarcMatcher::result_source_instance or Koha::Schema::Result::MarcModificationTemplate::result_source_instance or Koha::Schema::Result::MarcModificationTemplateAction::result_source_instance or Koha::Schema::Result::MarcSubfieldStructure::result_source_instance or Koha::Schema::Result::MarcTagStructure::result_source_instance or Koha::Schema::Result::Matchcheck::result_source_instance or Koha::Schema::Result::MatcherMatchpoint::result_source_instance or Koha::Schema::Result::Matchpoint::result_source_instance or Koha::Schema::Result::MatchpointComponent::result_source_instance or Koha::Schema::Result::MatchpointComponentNorm::result_source_instance or Koha::Schema::Result::Message::result_source_instance or Koha::Schema::Result::MessageAttribute::result_source_instance or Koha::Schema::Result::MessageQueue::result_source_instance or Koha::Schema::Result::MessageTransport::result_source_instance or Koha::Schema::Result::MessageTransportType::result_source_instance or Koha::Schema::Result::MiscFile::result_source_instance or Koha::Schema::Result::NeedMergeAuthority::result_source_instance or Koha::Schema::Result::Notify::result_source_instance or Koha::Schema::Result::OaiSet::result_source_instance or Koha::Schema::Result::OaiSetsBiblio::result_source_instance or Koha::Schema::Result::OaiSetsDescription::result_source_instance or Koha::Schema::Result::OaiSetsMapping::result_source_instance or Koha::Schema::Result::OldIssue::result_source_instance or Koha::Schema::Result::OldReserve::result_source_instance or Koha::Schema::Result::OpacNews::result_source_instance or Koha::Schema::Result::Overduerule::result_source_instance or Koha::Schema::Result::OverduerulesTransportType::result_source_instance or Koha::Schema::Result::PatronList::result_source_instance or Koha::Schema::Result::PatronListPatron::result_source_instance or Koha::Schema::Result::Patronimage::result_source_instance or Koha::Schema::Result::PendingOfflineOperation::result_source_instance or Koha::Schema::Result::Permission::result_source_instance or Koha::Schema::Result::PluginData::result_source_instance or Koha::Schema::Result::Printer::result_source_instance or Koha::Schema::Result::PrintersProfile::result_source_instance or Koha::Schema::Result::Quote::result_source_instance or Koha::Schema::Result::Rating::result_source_instance or Koha::Schema::Result::RepeatableHoliday::result_source_instance or Koha::Schema::Result::ReportsDictionary::result_source_instance or Koha::Schema::Result::Reserve::result_source_instance or Koha::Schema::Result::Review::result_source_instance or Koha::Schema::Result::SavedReport::result_source_instance or Koha::Schema::Result::SavedSql::result_source_instance or Koha::Schema::Result::SearchHistory::result_source_instance or Koha::Schema::Result::Serial::result_source_instance or Koha::Schema::Result::Serialitem::result_source_instance or Koha::Schema::Result::ServicesThrottle::result_source_instance or Koha::Schema::Result::Session::result_source_instance or Koha::Schema::Result::SocialData::result_source_instance or Koha::Schema::Result::SpecialHoliday::result_source_instance or Koha::Schema::Result::Statistic::result_source_instance or Koha::Schema::Result::Stopword::result_source_instance or Koha::Schema::Result::Subscription::result_source_instance or Koha::Schema::Result::SubscriptionFrequency::result_source_instance or Koha::Schema::Result::SubscriptionNumberpattern::result_source_instance or Koha::Schema::Result::Subscriptionhistory::result_source_instance or Koha::Schema::Result::Subscriptionroutinglist::result_source_instance or Koha::Schema::Result::Suggestion::result_source_instance or Koha::Schema::Result::Systempreference::result_source_instance or Koha::Schema::Result::Tag::result_source_instance or Koha::Schema::Result::TagAll::result_source_instance or Koha::Schema::Result::TagsApproval::result_source_instance or Koha::Schema::Result::TagsIndex::result_source_instance or Koha::Schema::Result::TmpHoldsqueue::result_source_instance or Koha::Schema::Result::TransportCost::result_source_instance or Koha::Schema::Result::UploadedFile::result_source_instance or Koha::Schema::Result::UserPermission::result_source_instance or Koha::Schema::Result::Userflag::result_source_instance or Koha::Schema::Result::Virtualshelfcontent::result_source_instance or Koha::Schema::Result::Virtualshelfshare::result_source_instance or Koha::Schema::Result::Virtualshelve::result_source_instance or Koha::Schema::Result::Z3950server::result_source_instance or Koha::Schema::Result::Zebraqueue::result_source_instance at line 2 of (eval 167)[Class/Accessor/Grouped.pm:764], avg 3µs/call
# 7 times (41µs+0s) by DBIx::Class::mk_classaccessor at line 37 of DBIx/Class.pm, avg 6µs/call
# 5 times (42µs+0s) by DBIx::Class::AccessorGroup::set_component_class at line 32 of DBIx/Class/AccessorGroup.pm, avg 8µs/call
# 2 times (9µs+0s) by DBIx::Class::Storage::DBI::set_use_dbms_capability at line 1072 of DBIx/Class/Storage/DBI.pm, avg 4µs/call | ||||
410 | 180 | 124µs | if (length (ref ($_[0]) ) ) { # spent 124µs making 180 calls to Scalar::Util::reftype, avg 689ns/call | ||
411 | if (Scalar::Util::reftype $_[0] eq 'HASH') { | ||||
412 | return $_[0]->{$_[1]} = $_[2]; | ||||
413 | } else { | ||||
414 | Carp::croak('Cannot set inherited value on an object instance that is not hash-based'); | ||||
415 | }; | ||||
416 | } | ||||
417 | |||||
418 | 2 | 20µs | # spent 15µs (9+6) within Class::Accessor::Grouped::BEGIN@418 which was called:
# once (9µs+6µs) by base::import at line 418 # spent 15µs making 1 call to Class::Accessor::Grouped::BEGIN@418
# spent 6µs making 1 call to strict::unimport | ||
419 | ${$_[0].'::__cag_'.$_[1]} = $_[2]; | ||||
420 | } | ||||
421 | |||||
422 | =head2 get_component_class | ||||
423 | |||||
424 | =over 4 | ||||
425 | |||||
426 | =item Arguments: $field | ||||
427 | |||||
428 | Returns: $value | ||||
429 | |||||
430 | =back | ||||
431 | |||||
432 | Gets the value of the specified component class. | ||||
433 | |||||
434 | __PACKAGE__->mk_group_accessors('component_class' => 'result_class'); | ||||
435 | |||||
436 | $self->result_class->method(); | ||||
437 | |||||
438 | ## same as | ||||
439 | $self->get_component_class('result_class')->method(); | ||||
440 | |||||
441 | =cut | ||||
442 | |||||
443 | sub get_component_class { | ||||
444 | $_[0]->get_inherited($_[1]); | ||||
445 | }; | ||||
446 | |||||
447 | =head2 set_component_class | ||||
448 | |||||
449 | =over 4 | ||||
450 | |||||
451 | =item Arguments: $field, $class | ||||
452 | |||||
453 | Returns: $new_value | ||||
454 | |||||
455 | =back | ||||
456 | |||||
457 | Inherited accessor that automatically loads the specified class before setting | ||||
458 | it. This method will die if the specified class could not be loaded. | ||||
459 | |||||
460 | __PACKAGE__->mk_group_accessors('component_class' => 'result_class'); | ||||
461 | __PACKAGE__->result_class('MyClass'); | ||||
462 | |||||
463 | $self->result_class->method(); | ||||
464 | |||||
465 | =cut | ||||
466 | |||||
467 | sub set_component_class { | ||||
468 | if (defined $_[2] and length $_[2]) { | ||||
469 | # disable warnings, and prevent $_ being eaten away by a behind-the-scenes | ||||
470 | # module loading | ||||
471 | local ($^W, $_); | ||||
472 | |||||
473 | if (__CAG_ENV__::UNSTABLE_DOLLARAT) { | ||||
474 | my $err; | ||||
475 | { | ||||
476 | local $@; | ||||
477 | eval { Module::Runtime::use_package_optimistically($_[2]) } | ||||
478 | or $err = $@; | ||||
479 | } | ||||
480 | Carp::croak("Could not load $_[1] '$_[2]': $err") if defined $err; | ||||
481 | |||||
482 | } | ||||
483 | else { | ||||
484 | eval { Module::Runtime::use_package_optimistically($_[2]) } | ||||
485 | or Carp::croak("Could not load $_[1] '$_[2]': $@"); | ||||
486 | } | ||||
487 | }; | ||||
488 | |||||
489 | $_[0]->set_inherited($_[1], $_[2]); | ||||
490 | }; | ||||
491 | |||||
492 | =head1 INTERNAL METHODS | ||||
493 | |||||
494 | These methods are documented for clarity, but are never meant to be called | ||||
495 | directly, and are not really meant for overriding either. | ||||
496 | |||||
497 | =head2 get_super_paths | ||||
498 | |||||
499 | Returns a list of 'parent' or 'super' class names that the current class | ||||
500 | inherited from. This is what drives the traversal done by L</get_inherited>. | ||||
501 | |||||
502 | =cut | ||||
503 | |||||
504 | # spent 2.43ms (1.90+522µs) within Class::Accessor::Grouped::get_super_paths which was called 182 times, avg 13µs/call:
# 182 times (1.90ms+522µs) by Class::Accessor::Grouped::get_inherited at line 384, avg 13µs/call | ||||
505 | # get_linear_isa returns the class itself as the 1st element | ||||
506 | # use @_ as a pre-allocated scratch array | ||||
507 | 1 | 17µs | 182 | 522µs | (undef, @_) = @{mro::get_linear_isa( length( ref($_[0]) ) ? ref($_[0]) : $_[0] )}; # spent 522µs making 182 calls to mro::get_linear_isa, avg 3µs/call |
508 | 1 | 5µs | @_; | ||
509 | }; | ||||
510 | |||||
511 | =head2 make_group_accessor | ||||
512 | |||||
513 | __PACKAGE__->make_group_accessor('simple', 'hair_length', 'hair_length'); | ||||
514 | __PACKAGE__->make_group_accessor('simple', 'hc', 'hair_color'); | ||||
515 | |||||
516 | =over 4 | ||||
517 | |||||
518 | =item Arguments: $group, $field, $accessor | ||||
519 | |||||
520 | Returns: \&accessor_coderef ? | ||||
521 | |||||
522 | =back | ||||
523 | |||||
524 | Called by mk_group_accessors for each entry in @fieldspec. Either returns | ||||
525 | a coderef which will be installed at C<&__PACKAGE__::$accessor>, or returns | ||||
526 | C<undef> if it elects to install the coderef on its own. | ||||
527 | |||||
528 | =cut | ||||
529 | |||||
530 | 3932 | 677ms | # spent 703ms (25.5+677) within Class::Accessor::Grouped::make_group_accessor which was called 3932 times, avg 179µs/call:
# 3932 times (25.5ms+677ms) by Class::Accessor::Grouped::_mk_group_accessors at line 146, avg 179µs/call # spent 677ms making 3932 calls to Class::Accessor::Grouped::__ANON__[Class/Accessor/Grouped.pm:942], avg 172µs/call | ||
531 | |||||
532 | =head2 make_group_ro_accessor | ||||
533 | |||||
534 | __PACKAGE__->make_group_ro_accessor('simple', 'birthdate', 'birthdate'); | ||||
535 | __PACKAGE__->make_group_ro_accessor('simple', 'ssn', 'social_security_number'); | ||||
536 | |||||
537 | =over 4 | ||||
538 | |||||
539 | =item Arguments: $group, $field, $accessor | ||||
540 | |||||
541 | Returns: \&accessor_coderef ? | ||||
542 | |||||
543 | =back | ||||
544 | |||||
545 | Called by mk_group_ro_accessors for each entry in @fieldspec. Either returns | ||||
546 | a coderef which will be installed at C<&__PACKAGE__::$accessor>, or returns | ||||
547 | C<undef> if it elects to install the coderef on its own. | ||||
548 | |||||
549 | =cut | ||||
550 | |||||
551 | sub make_group_ro_accessor { $gen_accessor->('ro', @_) } | ||||
552 | |||||
553 | =head2 make_group_wo_accessor | ||||
554 | |||||
555 | __PACKAGE__->make_group_wo_accessor('simple', 'lie', 'lie'); | ||||
556 | __PACKAGE__->make_group_wo_accessor('simple', 'subj', 'subject'); | ||||
557 | |||||
558 | =over 4 | ||||
559 | |||||
560 | =item Arguments: $group, $field, $accessor | ||||
561 | |||||
562 | Returns: \&accessor_coderef ? | ||||
563 | |||||
564 | =back | ||||
565 | |||||
566 | Called by mk_group_wo_accessors for each entry in @fieldspec. Either returns | ||||
567 | a coderef which will be installed at C<&__PACKAGE__::$accessor>, or returns | ||||
568 | C<undef> if it elects to install the coderef on its own. | ||||
569 | |||||
570 | =cut | ||||
571 | |||||
572 | sub make_group_wo_accessor { $gen_accessor->('wo', @_) } | ||||
573 | |||||
574 | |||||
575 | =head1 PERFORMANCE | ||||
576 | |||||
577 | To provide total flexibility L<Class::Accessor::Grouped> calls methods | ||||
578 | internally while performing get/set actions, which makes it noticeably | ||||
579 | slower than similar modules. To compensate, this module will automatically | ||||
580 | use the insanely fast L<Class::XSAccessor> to generate the C<simple>-group | ||||
581 | accessors if this module is available on your system. | ||||
582 | |||||
583 | =head2 Benchmark | ||||
584 | |||||
585 | This is the benchmark of 200 get/get/set/get/set cycles on perl 5.16.2 with | ||||
586 | thread support, showcasing how this modules L<simple (CAG_S)|/get_simple>, | ||||
587 | L<inherited (CAG_INH)|/get_inherited> and L<inherited with parent-class data | ||||
588 | (CAG_INHP)|/get_inherited> accessors stack up against most popular accessor | ||||
589 | builders: L<Moose>, L<Moo>, L<Mo>, L<Mouse> (both pure-perl and XS variant), | ||||
590 | L<Object::Tiny::RW (OTRW)|Object::Tiny::RW>, | ||||
591 | L<Class::Accessor (CA)|Class::Accessor>, | ||||
592 | L<Class::Accessor::Lite (CAL)|Class::Accessor::Lite>, | ||||
593 | L<Class::Accessor::Fast (CAF)|Class::Accessor::Fast>, | ||||
594 | L<Class::Accessor::Fast::XS (CAF_XS)|Class::Accessor::Fast::XS> | ||||
595 | and L<Class::XSAccessor (XSA)|Class::XSAccessor> | ||||
596 | |||||
597 | Rate CAG_INHP CAG_INH CA CAG_S CAF moOse OTRW CAL mo moUse HANDMADE moo CAF_XS moUse_XS XSA | ||||
598 | |||||
599 | CAG_INHP 287.021+-0.02/s -- -0.3% -10.0% -37.1% -53.1% -53.6% -53.7% -54.1% -56.9% -59.0% -59.6% -59.8% -78.7% -81.9% -83.5% | ||||
600 | |||||
601 | CAG_INH 288.025+-0.031/s 0.3% -- -9.7% -36.9% -52.9% -53.5% -53.5% -53.9% -56.7% -58.8% -59.5% -59.7% -78.6% -81.9% -83.5% | ||||
602 | |||||
603 | CA 318.967+-0.047/s 11.1% 10.7% -- -30.1% -47.9% -48.5% -48.5% -49.0% -52.1% -54.4% -55.1% -55.3% -76.3% -79.9% -81.7% | ||||
604 | |||||
605 | CAG_S 456.107+-0.054/s 58.9% 58.4% 43.0% -- -25.4% -26.3% -26.4% -27.0% -31.5% -34.8% -35.8% -36.1% -66.1% -71.3% -73.9% | ||||
606 | |||||
607 | CAF 611.745+-0.099/s 113.1% 112.4% 91.8% 34.1% -- -1.2% -1.2% -2.1% -8.1% -12.6% -14.0% -14.3% -54.5% -61.5% -64.9% | ||||
608 | |||||
609 | moOse 619.051+-0.059/s 115.7% 114.9% 94.1% 35.7% 1.2% -- -0.1% -1.0% -7.0% -11.6% -12.9% -13.3% -54.0% -61.0% -64.5% | ||||
610 | |||||
611 | OTRW 619.475+-0.1/s 115.8% 115.1% 94.2% 35.8% 1.3% 0.1% -- -0.9% -6.9% -11.5% -12.9% -13.2% -54.0% -61.0% -64.5% | ||||
612 | |||||
613 | CAL 625.106+-0.085/s 117.8% 117.0% 96.0% 37.1% 2.2% 1.0% 0.9% -- -6.1% -10.7% -12.1% -12.5% -53.5% -60.6% -64.2% | ||||
614 | |||||
615 | mo 665.44+-0.12/s 131.8% 131.0% 108.6% 45.9% 8.8% 7.5% 7.4% 6.5% -- -4.9% -6.4% -6.8% -50.5% -58.1% -61.9% | ||||
616 | |||||
617 | moUse 699.9+-0.15/s 143.9% 143.0% 119.4% 53.5% 14.4% 13.1% 13.0% 12.0% 5.2% -- -1.6% -2.0% -48.0% -55.9% -59.9% | ||||
618 | |||||
619 | HANDMADE 710.98+-0.16/s 147.7% 146.8% 122.9% 55.9% 16.2% 14.9% 14.8% 13.7% 6.8% 1.6% -- -0.4% -47.2% -55.2% -59.2% | ||||
620 | |||||
621 | moo 714.04+-0.13/s 148.8% 147.9% 123.9% 56.6% 16.7% 15.3% 15.3% 14.2% 7.3% 2.0% 0.4% -- -46.9% -55.0% -59.1% | ||||
622 | |||||
623 | CAF_XS 1345.55+-0.051/s 368.8% 367.2% 321.8% 195.0% 120.0% 117.4% 117.2% 115.3% 102.2% 92.2% 89.3% 88.4% -- -15.3% -22.9% | ||||
624 | |||||
625 | moUse_XS 1588+-0.036/s 453.3% 451.3% 397.9% 248.2% 159.6% 156.5% 156.3% 154.0% 138.6% 126.9% 123.4% 122.4% 18.0% -- -9.0% | ||||
626 | |||||
627 | XSA 1744.67+-0.052/s 507.9% 505.7% 447.0% 282.5% 185.2% 181.8% 181.6% 179.1% 162.2% 149.3% 145.4% 144.3% 29.7% 9.9% -- | ||||
628 | |||||
629 | Benchmarking program is available in the root of the | ||||
630 | L<repository|http://search.cpan.org/dist/Class-Accessor-Grouped/>: | ||||
631 | |||||
632 | =head2 Notes on Class::XSAccessor | ||||
633 | |||||
634 | You can force (or disable) the use of L<Class::XSAccessor> before creating a | ||||
635 | particular C<simple> accessor by either manipulating the global variable | ||||
636 | C<$Class::Accessor::Grouped::USE_XS> to true or false (preferably with | ||||
637 | L<localization|perlfunc/local>, or you can do so before runtime via the | ||||
638 | C<CAG_USE_XS> environment variable. | ||||
639 | |||||
640 | Since L<Class::XSAccessor> has no knowledge of L</get_simple> and | ||||
641 | L</set_simple> this module does its best to detect if you are overriding | ||||
642 | one of these methods and will fall back to using the perl version of the | ||||
643 | accessor in order to maintain consistency. However be aware that if you | ||||
644 | enable use of C<Class::XSAccessor> (automatically or explicitly), create | ||||
645 | an object, invoke a simple accessor on that object, and B<then> manipulate | ||||
646 | the symbol table to install a C<get/set_simple> override - you get to keep | ||||
647 | all the pieces. | ||||
648 | |||||
649 | =head1 AUTHORS | ||||
650 | |||||
651 | Matt S. Trout <mst@shadowcatsystems.co.uk> | ||||
652 | |||||
653 | Christopher H. Laco <claco@chrislaco.com> | ||||
654 | |||||
655 | =head1 CONTRIBUTORS | ||||
656 | |||||
657 | Caelum: Rafael Kitover <rkitover@cpan.org> | ||||
658 | |||||
659 | frew: Arthur Axel "fREW" Schmidt <frioux@gmail.com> | ||||
660 | |||||
661 | groditi: Guillermo Roditi <groditi@cpan.org> | ||||
662 | |||||
663 | Jason Plum <jason.plum@bmmsi.com> | ||||
664 | |||||
665 | ribasushi: Peter Rabbitson <ribasushi@cpan.org> | ||||
666 | |||||
667 | |||||
668 | =head1 COPYRIGHT & LICENSE | ||||
669 | |||||
670 | Copyright (c) 2006-2010 Matt S. Trout <mst@shadowcatsystems.co.uk> | ||||
671 | |||||
672 | This program is free software; you can redistribute it and/or modify | ||||
673 | it under the same terms as perl itself. | ||||
674 | |||||
675 | =cut | ||||
676 | |||||
677 | ######################################################################## | ||||
678 | ######################################################################## | ||||
679 | ######################################################################## | ||||
680 | # | ||||
681 | # Here be many angry dragons | ||||
682 | # (all code is in private coderefs since everything inherits CAG) | ||||
683 | # | ||||
684 | ######################################################################## | ||||
685 | ######################################################################## | ||||
686 | |||||
687 | # Autodetect unless flag supplied | ||||
688 | my $xsa_autodetected; | ||||
689 | if (! defined $USE_XS) { | ||||
690 | $USE_XS = __CAG_ENV__::NO_CXSA ? 0 : 1; | ||||
691 | $xsa_autodetected++; | ||||
692 | } | ||||
693 | |||||
694 | |||||
695 | my $maker_templates = { | ||||
696 | rw => { | ||||
697 | cxsa_call => 'accessors', | ||||
698 | # spent 8.92ms (6.57+2.35) within Class::Accessor::Grouped::__ANON__[/usr/share/perl5/Class/Accessor/Grouped.pm:708] which was called 927 times, avg 10µs/call:
# 927 times (6.57ms+2.35ms) by Class::Accessor::Grouped::__ANON__[/usr/share/perl5/Class/Accessor/Grouped.pm:942] at line 936, avg 10µs/call | ||||
699 | # my ($group, $fieldname) = @_; | ||||
700 | 927 | 2.35ms | my $quoted_fieldname = __CAG_ENV__::perlstring($_[1]); # spent 2.35ms making 927 calls to __CAG_ENV__::perlstring, avg 3µs/call | ||
701 | sprintf <<'EOS', ($_[0], $quoted_fieldname) x 2; | ||||
702 | |||||
703 | @_ > 1 | ||||
704 | ? shift->set_%s(%s, @_) | ||||
705 | : shift->get_%s(%s) | ||||
706 | EOS | ||||
707 | |||||
708 | }, | ||||
709 | }, | ||||
710 | ro => { | ||||
711 | cxsa_call => 'getters', | ||||
712 | pp_generator => sub { | ||||
713 | # my ($group, $fieldname) = @_; | ||||
714 | my $quoted_fieldname = __CAG_ENV__::perlstring($_[1]); | ||||
715 | sprintf <<'EOS', $_[0], $quoted_fieldname; | ||||
716 | |||||
717 | @_ > 1 | ||||
718 | ? do { | ||||
719 | my ($meth) = (caller(0))[3] =~ /([^\:]+)$/; | ||||
720 | my $class = length( ref($_[0]) ) ? ref($_[0]) : $_[0]; | ||||
721 | Carp::croak( | ||||
722 | "'$meth' cannot alter its value (read-only attribute of class $class)" | ||||
723 | ); | ||||
724 | } | ||||
725 | : shift->get_%s(%s) | ||||
726 | EOS | ||||
727 | |||||
728 | }, | ||||
729 | }, | ||||
730 | wo => { | ||||
731 | cxsa_call => 'setters', | ||||
732 | pp_generator => sub { | ||||
733 | # my ($group, $fieldname) = @_; | ||||
734 | my $quoted_fieldname = __CAG_ENV__::perlstring($_[1]); | ||||
735 | sprintf <<'EOS', $_[0], $quoted_fieldname; | ||||
736 | |||||
737 | @_ > 1 | ||||
738 | ? shift->set_%s(%s, @_) | ||||
739 | : do { | ||||
740 | my ($meth) = (caller(0))[3] =~ /([^\:]+)$/; | ||||
741 | my $class = length( ref($_[0]) ) ? ref($_[0]) : $_[0]; | ||||
742 | Carp::croak( | ||||
743 | "'$meth' cannot access its value (write-only attribute of class $class)" | ||||
744 | ); | ||||
745 | } | ||||
746 | EOS | ||||
747 | |||||
748 | }, | ||||
749 | }, | ||||
750 | }; | ||||
751 | |||||
752 | # spent 592ms (526+66.3) within Class::Accessor::Grouped::__ANON__[/usr/share/perl5/Class/Accessor/Grouped.pm:774] which was called 927 times, avg 639µs/call:
# 927 times (526ms+66.3ms) by Class::Accessor::Grouped::__ANON__[/usr/share/perl5/Class/Accessor/Grouped.pm:942] at line 939, avg 639µs/call | ||||
753 | #my ($src, $no_warnings, $err_msg) = @_; | ||||
754 | |||||
755 | my $src = sprintf "{ %s warnings; use strict; no strict 'refs'; %s }", | ||||
756 | $_[1] ? 'no' : 'use', | ||||
757 | $_[0], | ||||
758 | ; | ||||
759 | |||||
760 | my (@rv, $err); | ||||
761 | { | ||||
762 | local $@ if __CAG_ENV__::UNSTABLE_DOLLARAT; | ||||
763 | wantarray | ||||
764 | ? @rv = eval $src # spent 0s executing statements in 927 string evals (merged) # includes 102ms spent executing 10796 calls to 6389 subs defined therein. | ||||
765 | : $rv[0] = eval $src | ||||
766 | ; | ||||
767 | $err = $@ if $@ ne ''; | ||||
768 | } | ||||
769 | |||||
770 | Carp::croak(join ': ', ($_[2] || 'String-eval failed'), "$err\n$src\n" ) | ||||
771 | if defined $err; | ||||
772 | |||||
773 | wantarray ? @rv : $rv[0]; | ||||
774 | }; | ||||
775 | |||||
776 | my ($accessor_maker_cache, $no_xsa_warned_classes); | ||||
777 | |||||
778 | # can't use pkg_gen to track this stuff, as it doesn't | ||||
779 | # detect superclass mucking | ||||
780 | 1 | 3µs | my $original_simple_getter = __PACKAGE__->can ('get_simple'); # spent 3µs making 1 call to UNIVERSAL::can | ||
781 | 1 | 1µs | my $original_simple_setter = __PACKAGE__->can ('set_simple'); # spent 1µs making 1 call to UNIVERSAL::can | ||
782 | |||||
783 | my ($resolved_methods, $cag_produced_crefs); | ||||
784 | |||||
785 | sub CLONE { | ||||
786 | my @crefs = grep { defined $_ } values %{$cag_produced_crefs||{}}; | ||||
787 | $cag_produced_crefs = @crefs | ||||
788 | ? { map { $_ => $_ } @crefs } | ||||
789 | : undef | ||||
790 | ; | ||||
791 | } | ||||
792 | |||||
793 | # Note!!! Unusual signature | ||||
794 | # spent 677ms (62.8+614) within Class::Accessor::Grouped::__ANON__[/usr/share/perl5/Class/Accessor/Grouped.pm:942] which was called 3932 times, avg 172µs/call:
# 3932 times (62.8ms+614ms) by Class::Accessor::Grouped::make_group_accessor at line 530, avg 172µs/call | ||||
795 | my ($type, $class, $group, $field, $methname) = @_; | ||||
796 | $class = ref $class if length ref $class; | ||||
797 | |||||
798 | # When installing an XSA simple accessor, we need to make sure we are not | ||||
799 | # short-circuiting a (compile or runtime) get_simple/set_simple override. | ||||
800 | # What we do here is install a lazy first-access check, which will decide | ||||
801 | # the ultimate coderef being placed in the accessor slot | ||||
802 | # | ||||
803 | # Also note that the *original* class will always retain this shim, as | ||||
804 | # different branches inheriting from it may have different overrides. | ||||
805 | # Thus the final method (properly labeled and all) is installed in the | ||||
806 | # calling-package's namespace | ||||
807 | if ($USE_XS and $group eq 'simple') { | ||||
808 | die sprintf( "Class::XSAccessor requested but not available:\n%s\n", __CAG_ENV__::NO_CXSA ) | ||||
809 | if __CAG_ENV__::NO_CXSA; | ||||
810 | |||||
811 | # spent 198µs (53+145) within DBIx::Class::ResultSource::name which was called:
# once (53µs+145µs) by DBIx::Class::ResultSourceProxy::Table::table at line 104 of DBIx/Class/ResultSourceProxy/Table.pm
# spent 160µs (56+104) within DBIx::Class::ResultSource::_primaries which was called:
# once (56µs+104µs) by DBIx::Class::ResultSource::set_primary_key at line 617 of DBIx/Class/ResultSource.pm
# spent 179µs (60+119) within DBIx::Class::ResultSource::source_name which was called:
# once (60µs+119µs) by DBIx::Class::Schema::load_namespaces at line 279 of DBIx/Class/Schema.pm
# spent 103µs (34+69) within DBIx::Class::Storage::transaction_depth which was called:
# once (34µs+69µs) by DBIx::Class::Storage::DBI::dbh_do at line 837 of DBIx/Class/Storage/DBI.pm
# spent 86µs (28+59) within DBIx::Class::ResultSource::_columns which was called:
# once (28µs+59µs) by DBIx::Class::ResultSource::add_columns at line 332 of DBIx/Class/ResultSource.pm
# spent 154µs (47+107) within DBIx::Class::ResultSource::_relationships which was called:
# once (47µs+107µs) by DBIx::Class::ResultSource::add_relationship at line 1349 of DBIx/Class/ResultSource.pm
# spent 240µs (80+160) within DBIx::Class::ResultSet::result_source which was called 2 times, avg 120µs/call:
# once (79µs+160µs) by DBIx::Class::ResultSet::search_rs at line 432 of DBIx/Class/ResultSet.pm
# once (1µs+0s) by DBIx::Class::ResultSet::search_rs at line 913
# spent 93µs (30+63) within DBIx::Class::Storage::DBI::on_connect_do which was called 3 times, avg 31µs/call:
# once (29µs+63µs) by DBIx::Class::Storage::DBI::connect_info at line 652 of DBIx/Class/Storage/DBI.pm
# once (800ns+0s) by DBIx::Class::Storage::DBI::_parse_connect_do at line 779 of DBIx/Class/Storage/DBI.pm
# once (400ns+0s) by DBIx::Class::Storage::DBI::connect_info at line 913
# spent 200µs (54+146) within DBIx::Class::Storage::schema which was called:
# once (54µs+146µs) by DBIx::Class::Storage::set_schema at line 74 of DBIx/Class/Storage.pm
# spent 98µs (30+69) within DBIx::Class::ResultSource::_ordered_columns which was called:
# once (30µs+69µs) by DBIx::Class::ResultSource::add_columns at line 329 of DBIx/Class/ResultSource.pm
# spent 176µs (60+115) within DBIx::Class::Storage::DBI::_conn_pid which was called 3 times, avg 59µs/call:
# once (57µs+115µs) by DBIx::Class::Storage::DBI::_populate_dbh at line 1048 of DBIx/Class/Storage/DBI.pm
# once (3µs+0s) by DBIx::Class::Storage::DBI::_verify_pid at line 271 of DBIx/Class/Storage/DBI.pm
# once (1µs+0s) by DBIx::Class::Storage::DBI::_populate_dbh at line 913
# spent 248µs (78+170) within DBIx::Class::Storage::DBI::_dbh_autocommit which was called 3 times, avg 83µs/call:
# once (76µs+170µs) by DBIx::Class::Storage::DBI::_connect at line 1531 of DBIx/Class/Storage/DBI.pm
# once (1µs+0s) by DBIx::Class::Storage::DBI::_populate_dbh at line 1054 of DBIx/Class/Storage/DBI.pm
# once (1µs+0s) by DBIx::Class::Storage::DBI::_connect at line 913
# spent 93µs (30+63) within DBIx::Class::Storage::DBI::_sql_maker which was called 2 times, avg 47µs/call:
# once (29µs+63µs) by DBIx::Class::Storage::DBI::connect_info at line 659 of DBIx/Class/Storage/DBI.pm
# once (400ns+0s) by DBIx::Class::Storage::DBI::connect_info at line 913
# spent 127µs (41+85) within DBIx::Class::Storage::DBI::unsafe which was called 3 times, avg 42µs/call:
# once (37µs+85µs) by DBIx::Class::Storage::DBI::connect_info at line 652 of DBIx/Class/Storage/DBI.pm
# once (4µs+0s) by Try::Tiny::try at line 1501 of DBIx/Class/Storage/DBI.pm
# once (500ns+0s) by DBIx::Class::Storage::DBI::connect_info at line 913
# spent 278µs (87+190) within DBIx::Class::Storage::debug which was called:
# once (87µs+190µs) by DBIx::Class::Storage::DBI::_query_start at line 1764 of DBIx/Class/Storage/DBI.pm
# spent 99µs (34+65) within DBIx::Class::Storage::DBI::_sql_maker_opts which was called 3 times, avg 33µs/call:
# once (32µs+65µs) by DBIx::Class::Storage::DBI::new at line 193 of DBIx/Class/Storage/DBI.pm
# once (1µs+0s) by DBIx::Class::Storage::DBI::connect_info at line 660 of DBIx/Class/Storage/DBI.pm
# once (500ns+0s) by DBIx::Class::Storage::DBI::new at line 913
# spent 101µs (38+63) within DBIx::Class::Storage::DBI::_dbic_connect_attributes which was called 3 times, avg 34µs/call:
# once (37µs+63µs) by DBIx::Class::Storage::DBI::connect_info at line 671 of DBIx/Class/Storage/DBI.pm
# once (1µs+0s) by DBIx::Class::Storage::DBI::mysql::_run_connection_actions at line 94 of DBIx/Class/Storage/DBI/mysql.pm
# once (600ns+0s) by DBIx::Class::Storage::DBI::connect_info at line 913
# spent 164µs (34+130) within DBIx::Class::Storage::DBI::_dbh_details which was called 3 times, avg 55µs/call:
# once (33µs+130µs) by DBIx::Class::Storage::DBI::new at line 194 of DBIx/Class/Storage/DBI.pm
# once (1µs+0s) by DBIx::Class::Storage::DBI::_populate_dbh at line 1041 of DBIx/Class/Storage/DBI.pm
# once (500ns+0s) by DBIx::Class::Storage::DBI::new at line 913
# spent 167µs (51+116) within DBIx::Class::Storage::DBI::on_connect_call which was called:
# once (51µs+116µs) by DBIx::Class::Storage::DBI::mysql::_run_connection_actions at line 1063 of DBIx/Class/Storage/DBI.pm
# spent 160µs (50+110) within DBIx::Class::Storage::DBI::_driver_determined which was called 3 times, avg 53µs/call:
# once (47µs+110µs) by DBIx::Class::Storage::DBI::_determine_driver at line 1248 of DBIx/Class/Storage/DBI.pm
# once (2µs+0s) by DBIx::Class::Storage::DBI::_determine_driver at line 1284 of DBIx/Class/Storage/DBI.pm
# once (800ns+0s) by DBIx::Class::Storage::DBI::_determine_driver at line 913
# spent 112µs (43+69) within DBIx::Class::Storage::DBI::_dbh which was called 10 times, avg 11µs/call:
# 2 times (1µs+0s) by DBIx::Class::Storage::DBI::mysql::_run_connection_actions at line 94 of DBIx/Class/Storage/DBI/mysql.pm, avg 600ns/call
# once (30µs+69µs) by Koha::Objects::search at line 960 of DBIx/Class/Storage/DBI.pm
# once (3µs+0s) by DBIx::Class::Storage::DBI::_populate_dbh at line 1058 of DBIx/Class/Storage/DBI.pm
# once (3µs+0s) by DBIx::Class::Storage::DBI::_get_dbh at line 969 of DBIx/Class/Storage/DBI.pm
# once (2µs+0s) by DBIx::Class::Storage::DBI::_populate_dbh at line 1046 of DBIx/Class/Storage/DBI.pm
# once (2µs+0s) by DBIx::Class::Storage::DBI::_determine_driver at line 1254 of DBIx/Class/Storage/DBI.pm
# once (1µs+0s) by DBIx::Class::Storage::DBI::_determine_driver at line 1255 of DBIx/Class/Storage/DBI.pm
# once (500ns+0s) by DBIx::Class::Storage::DBI::_populate_dbh at line 1039 of DBIx/Class/Storage/DBI.pm
# once (500ns+0s) by Koha::Objects::search at line 913
# spent 97µs (31+66) within DBIx::Class::ResultSource::_unique_constraints which was called:
# once (31µs+66µs) by DBIx::Class::ResultSource::unique_constraints at line 872 of DBIx/Class/ResultSource.pm
# spent 308µs (97+210) within DBIx::Class::ResultSet::_result_class which was called 4 times, avg 77µs/call:
# 2 times (93µs+210µs) by DBIx::Class::ResultSet::result_class at line 1569 of DBIx/Class/ResultSet.pm, avg 152µs/call
# once (3µs+0s) by DBIx::Class::ResultSet::result_class at line 1573 of DBIx/Class/ResultSet.pm
# once (1µs+0s) by DBIx::Class::ResultSet::result_class at line 913
# spent 110µs (33+77) within DBIx::Class::Storage::DBI::_connect_info which was called 3 times, avg 37µs/call:
# once (32µs+77µs) by DBIx::Class::Storage::DBI::connect_info at line 620 of DBIx/Class/Storage/DBI.pm
# once (800ns+0s) by DBIx::Class::Storage::DBI::connect_info at line 673 of DBIx/Class/Storage/DBI.pm
# once (600ns+0s) by DBIx::Class::Storage::DBI::connect_info at line 913 | ||||
812 | my $current_class = length (ref ($_[0] ) ) ? ref ($_[0]) : $_[0]; | ||||
813 | |||||
814 | my $resolved_implementation = $resolved_methods->{$current_class}{$methname} ||= do { | ||||
815 | 48 | 193µs | if ( # spent 193µs making 48 calls to UNIVERSAL::can, avg 4µs/call | ||
816 | ($current_class->can('get_simple')||0) == $original_simple_getter | ||||
817 | && | ||||
818 | ($current_class->can('set_simple')||0) == $original_simple_setter | ||||
819 | ) { | ||||
820 | # nothing has changed, might as well use the XS crefs | ||||
821 | # | ||||
822 | # note that by the time this code executes, we already have | ||||
823 | # *objects* (since XSA works on 'simple' only by definition). | ||||
824 | # If someone is mucking with the symbol table *after* there | ||||
825 | # are some objects already - look! many, shiny pieces! :) | ||||
826 | # | ||||
827 | # The weird breeder thingy is because XSA does not have an | ||||
828 | # interface returning *just* a coderef, without installing it | ||||
829 | # anywhere :( | ||||
830 | 24 | 2.14ms | Class::XSAccessor->import( # spent 2.14ms making 24 calls to Class::XSAccessor::import, avg 89µs/call | ||
831 | replace => 1, | ||||
832 | class => '__CAG__XSA__BREEDER__', | ||||
833 | $maker_templates->{$type}{cxsa_call} => { | ||||
834 | $methname => $field, | ||||
835 | }, | ||||
836 | ); | ||||
837 | 24 | 49µs | __CAG__XSA__BREEDER__->can($methname); # spent 49µs making 24 calls to UNIVERSAL::can, avg 2µs/call | ||
838 | } | ||||
839 | else { | ||||
840 | if (! $xsa_autodetected and ! $no_xsa_warned_classes->{$current_class}++) { | ||||
841 | # not using Carp since the line where this happens doesn't mean much | ||||
842 | warn 'Explicitly requested use of Class::XSAccessor disabled for objects of class ' | ||||
843 | . "'$current_class' inheriting from '$class' due to an overriden get_simple and/or " | ||||
844 | . "set_simple\n"; | ||||
845 | } | ||||
846 | |||||
847 | do { | ||||
848 | # that's faster than local | ||||
849 | $USE_XS = 0; | ||||
850 | my $c = $gen_accessor->($type, $class, 'simple', $field, $methname); | ||||
851 | $USE_XS = 1; | ||||
852 | $c; | ||||
853 | }; | ||||
854 | } | ||||
855 | }; | ||||
856 | |||||
857 | # if after this shim was created someone wrapped it with an 'around', | ||||
858 | # we can not blindly reinstall the method slot - we will destroy the | ||||
859 | # wrapper. Silently chain execution further... | ||||
860 | 24 | 48µs | if ( ! $cag_produced_crefs->{ $current_class->can($methname) || 0 } ) { # spent 48µs making 24 calls to UNIVERSAL::can, avg 2µs/call | ||
861 | |||||
862 | # older perls segfault if the cref behind the goto throws | ||||
863 | # http://rt.perl.org/rt3/Public/Bug/Display.html?id=35878 | ||||
864 | return $resolved_implementation->(@_) if __CAG_ENV__::BROKEN_GOTO; | ||||
865 | |||||
866 | goto $resolved_implementation; | ||||
867 | } | ||||
868 | |||||
869 | |||||
870 | if (__CAG_ENV__::TRACK_UNDEFER_FAIL) { | ||||
871 | my $deferred_calls_seen = do { | ||||
872 | 2 | 94µs | # spent 78µs (62+16) within Class::Accessor::Grouped::BEGIN@872 which was called:
# once (62µs+16µs) by base::import at line 872 # spent 78µs making 1 call to Class::Accessor::Grouped::BEGIN@872
# spent 16µs making 1 call to strict::unimport | ||
873 | \%{"${current_class}::__cag_deferred_xs_shim_invocations"} | ||||
874 | }; | ||||
875 | my @cframe = caller(0); | ||||
876 | |||||
877 | if (my $already_seen = $deferred_calls_seen->{$cframe[3]}) { | ||||
878 | Carp::carp ( | ||||
879 | "Deferred version of method $cframe[3] invoked more than once (originally " | ||||
880 | . "invoked at $already_seen). This is a strong indication your code has " | ||||
881 | . 'cached the original ->can derived method coderef, and is using it instead ' | ||||
882 | . 'of the proper method re-lookup, causing minor performance regressions' | ||||
883 | ); | ||||
884 | } | ||||
885 | else { | ||||
886 | $deferred_calls_seen->{$cframe[3]} = "$cframe[1] line $cframe[2]"; | ||||
887 | } | ||||
888 | } | ||||
889 | |||||
890 | # install the resolved implementation into the code slot so we do not | ||||
891 | # come here anymore (hopefully) | ||||
892 | # since XSAccessor was available - so is Sub::Name | ||||
893 | { | ||||
894 | 2 | 21µs | # spent 16µs (11+5) within Class::Accessor::Grouped::BEGIN@894 which was called:
# once (11µs+5µs) by base::import at line 894 # spent 16µs making 1 call to Class::Accessor::Grouped::BEGIN@894
# spent 5µs making 1 call to strict::unimport | ||
895 | 2 | 30µs | # spent 20µs (9+10) within Class::Accessor::Grouped::BEGIN@895 which was called:
# once (9µs+10µs) by base::import at line 895 # spent 20µs making 1 call to Class::Accessor::Grouped::BEGIN@895
# spent 10µs making 1 call to warnings::unimport | ||
896 | |||||
897 | my $fq_name = "${current_class}::${methname}"; | ||||
898 | 24 | 111µs | *$fq_name = Sub::Name::subname($fq_name, $resolved_implementation); # spent 111µs making 24 calls to Sub::Name::subname, avg 5µs/call | ||
899 | } | ||||
900 | |||||
901 | # now things are installed - one ref less to carry | ||||
902 | delete $resolved_methods->{$current_class}{$methname}; | ||||
903 | |||||
904 | # but need to record it in the expectation registry *in case* it | ||||
905 | # was cached via ->can for some moronic reason | ||||
906 | 24 | 34µs | Scalar::Util::weaken( $cag_produced_crefs->{$resolved_implementation} = $resolved_implementation ); # spent 34µs making 24 calls to Scalar::Util::weaken, avg 1µs/call | ||
907 | |||||
908 | |||||
909 | # older perls segfault if the cref behind the goto throws | ||||
910 | # http://rt.perl.org/rt3/Public/Bug/Display.html?id=35878 | ||||
911 | return $resolved_implementation->(@_) if __CAG_ENV__::BROKEN_GOTO; | ||||
912 | |||||
913 | 24 | 16µs | goto $resolved_implementation; # spent 1µs making 1 call to DBIx::Class::ResultSet::_result_class
# spent 1µs making 1 call to DBIx::Class::Storage::DBI::mysql::debug
# spent 1µs making 1 call to DBIx::Class::ResultSet::result_source
# spent 1µs making 1 call to DBIx::Class::Storage::DBI::_conn_pid
# spent 1µs making 1 call to DBIx::Class::Storage::DBI::_dbh_autocommit
# spent 800ns making 1 call to DBIx::Class::Storage::DBI::_driver_determined
# spent 600ns making 1 call to DBIx::Class::ResultSource::Table::_columns
# spent 600ns making 1 call to DBIx::Class::ResultSource::Table::source_name
# spent 600ns making 1 call to DBIx::Class::Storage::DBI::_connect_info
# spent 600ns making 1 call to DBIx::Class::Storage::DBI::_dbic_connect_attributes
# spent 600ns making 1 call to DBIx::Class::Storage::DBI::schema
# spent 500ns making 1 call to DBIx::Class::ResultSource::Table::_primaries
# spent 500ns making 1 call to DBIx::Class::ResultSource::Table::_relationships
# spent 500ns making 1 call to DBIx::Class::ResultSource::Table::_unique_constraints
# spent 500ns making 1 call to DBIx::Class::ResultSource::Table::name
# spent 500ns making 1 call to DBIx::Class::Storage::DBI::_dbh
# spent 500ns making 1 call to DBIx::Class::Storage::DBI::_dbh_details
# spent 500ns making 1 call to DBIx::Class::Storage::DBI::_sql_maker_opts
# spent 500ns making 1 call to DBIx::Class::Storage::DBI::mysql::on_connect_call
# spent 500ns making 1 call to DBIx::Class::Storage::DBI::unsafe
# spent 400ns making 1 call to DBIx::Class::ResultSource::Table::_ordered_columns
# spent 400ns making 1 call to DBIx::Class::Storage::DBI::_sql_maker
# spent 400ns making 1 call to DBIx::Class::Storage::DBI::mysql::transaction_depth
# spent 400ns making 1 call to DBIx::Class::Storage::DBI::on_connect_do | ||
914 | }; | ||||
915 | |||||
916 | 78 | 70µs | Scalar::Util::weaken($cag_produced_crefs->{$ret} = $ret); # spent 70µs making 78 calls to Scalar::Util::weaken, avg 899ns/call | ||
917 | |||||
918 | $ret; # returning shim | ||||
919 | } | ||||
920 | |||||
921 | # no Sub::Name - just install the coderefs directly (compiling every time) | ||||
922 | elsif (__CAG_ENV__::NO_SUBNAME) { | ||||
923 | my $src = $accessor_maker_cache->{source}{$type}{$group}{$field} ||= | ||||
924 | $maker_templates->{$type}{pp_generator}->($group, $field); | ||||
925 | |||||
926 | $cag_eval->( | ||||
927 | "no warnings 'redefine'; sub ${class}::${methname} { $src }; 1", | ||||
928 | ); | ||||
929 | |||||
930 | undef; # so that no further attempt will be made to install anything | ||||
931 | } | ||||
932 | |||||
933 | # a coderef generator with a variable pad (returns a fresh cref on every invocation) | ||||
934 | else { | ||||
935 | 3854 | 13.0ms | ($accessor_maker_cache->{pp}{$type}{$group}{$field} ||= do { # spent 13.0ms making 3854 calls to Class::Accessor::Grouped::__ANON__[(eval 1000)[Class/Accessor/Grouped.pm:764]:5], avg 3µs/call | ||
936 | 927 | 8.92ms | my $src = $accessor_maker_cache->{source}{$type}{$group}{$field} ||= # spent 8.92ms making 927 calls to Class::Accessor::Grouped::__ANON__[Class/Accessor/Grouped.pm:708], avg 10µs/call | ||
937 | $maker_templates->{$type}{pp_generator}->($group, $field); | ||||
938 | |||||
939 | 927 | 592ms | $cag_eval->( "sub { my \$dummy; sub { \$dummy if 0; $src } }" ); # spent 592ms making 927 calls to Class::Accessor::Grouped::__ANON__[Class/Accessor/Grouped.pm:774], avg 639µs/call | ||
940 | })->() | ||||
941 | } | ||||
942 | }; | ||||
943 | |||||
944 | 1; | ||||
# spent 6.16ms within Class::Accessor::Grouped::CORE:match which was called 3933 times, avg 2µs/call:
# 1966 times (4.89ms+0s) by Class::Accessor::Grouped::_mk_group_accessors at line 97, avg 2µs/call
# 1966 times (1.26ms+0s) by Class::Accessor::Grouped::_mk_group_accessors at line 137, avg 641ns/call
# once (3µs+0s) by base::import at line 19 | |||||
sub __CAG_ENV__::__ANON__; # xsub |