| 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 | Class::Accessor::Grouped::__ANON__[:774] |
| 1920 | 1 | 1 | 111ms | 851ms | Class::Accessor::Grouped::_mk_group_accessors |
| 3932 | 1 | 1 | 62.8ms | 677ms | Class::Accessor::Grouped::__ANON__[:942] |
| 3932 | 1 | 1 | 25.5ms | 703ms | Class::Accessor::Grouped::make_group_accessor |
| 1920 | 18 | 9 | 23.7ms | 874ms | Class::Accessor::Grouped::mk_group_accessors |
| 3450 | 2 | 2 | 21.4ms | 24.3ms | Class::Accessor::Grouped::get_inherited |
| 927 | 1 | 1 | 6.57ms | 8.92ms | Class::Accessor::Grouped::__ANON__[:708] |
| 3933 | 3 | 1 | 6.16ms | 6.16ms | Class::Accessor::Grouped::CORE:match (opcode) |
| 720 | 4 | 4 | 2.44ms | 2.56ms | Class::Accessor::Grouped::set_inherited |
| 927 | 1 | 1 | 2.35ms | 2.35ms | __CAG_ENV__::perlstring |
| 182 | 1 | 1 | 1.90ms | 2.43ms | Class::Accessor::Grouped::get_super_paths |
| 4 | 3 | 2 | 97µs | 308µs | DBIx::Class::ResultSet::_result_class |
| 1 | 1 | 1 | 87µs | 278µs | DBIx::Class::Storage::debug |
| 2 | 2 | 2 | 80µs | 240µs | DBIx::Class::ResultSet::result_source |
| 3 | 3 | 2 | 78µs | 248µs | DBIx::Class::Storage::DBI::_dbh_autocommit |
| 1 | 1 | 1 | 76µs | 2.09ms | Class::Accessor::Grouped::BEGIN@31 |
| 1 | 1 | 1 | 62µs | 78µs | Class::Accessor::Grouped::BEGIN@872 |
| 1 | 1 | 1 | 60µs | 179µs | DBIx::Class::ResultSource::source_name |
| 3 | 3 | 2 | 60µs | 176µs | DBIx::Class::Storage::DBI::_conn_pid |
| 1 | 1 | 1 | 56µs | 160µs | DBIx::Class::ResultSource::_primaries |
| 1 | 1 | 1 | 54µs | 200µs | DBIx::Class::Storage::schema |
| 1 | 1 | 1 | 53µs | 198µs | DBIx::Class::ResultSource::name |
| 1 | 1 | 1 | 51µs | 167µs | DBIx::Class::Storage::DBI::on_connect_call |
| 3 | 3 | 2 | 50µs | 160µs | DBIx::Class::Storage::DBI::_driver_determined |
| 1 | 1 | 1 | 47µs | 154µs | DBIx::Class::ResultSource::_relationships |
| 10 | 9 | 3 | 43µs | 112µs | DBIx::Class::Storage::DBI::_dbh |
| 3 | 3 | 2 | 41µs | 127µs | DBIx::Class::Storage::DBI::unsafe |
| 3 | 3 | 3 | 38µs | 101µs | DBIx::Class::Storage::DBI::_dbic_connect_attributes |
| 3 | 3 | 2 | 34µs | 164µs | DBIx::Class::Storage::DBI::_dbh_details |
| 3 | 3 | 2 | 34µs | 99µs | DBIx::Class::Storage::DBI::_sql_maker_opts |
| 1 | 1 | 1 | 34µs | 103µs | DBIx::Class::Storage::transaction_depth |
| 3 | 3 | 2 | 33µs | 110µs | DBIx::Class::Storage::DBI::_connect_info |
| 1 | 1 | 1 | 31µs | 97µs | DBIx::Class::ResultSource::_unique_constraints |
| 3 | 3 | 2 | 30µs | 93µs | DBIx::Class::Storage::DBI::on_connect_do |
| 2 | 2 | 2 | 30µs | 93µs | DBIx::Class::Storage::DBI::_sql_maker |
| 1 | 1 | 1 | 30µs | 98µs | DBIx::Class::ResultSource::_ordered_columns |
| 1 | 1 | 1 | 28µs | 86µs | DBIx::Class::ResultSource::_columns |
| 1 | 1 | 1 | 14µs | 20µs | Class::Accessor::Grouped::BEGIN@2 |
| 1 | 1 | 1 | 11µs | 18µs | Class::Accessor::Grouped::BEGIN@377 |
| 1 | 1 | 1 | 11µs | 16µs | Class::Accessor::Grouped::BEGIN@894 |
| 1 | 1 | 1 | 10µs | 17µs | Class::Accessor::Grouped::BEGIN@87 |
| 1 | 1 | 1 | 9µs | 20µs | Class::Accessor::Grouped::BEGIN@895 |
| 1 | 1 | 1 | 9µs | 15µs | Class::Accessor::Grouped::BEGIN@418 |
| 1 | 1 | 1 | 8µs | 19µs | Class::Accessor::Grouped::BEGIN@378 |
| 1 | 1 | 1 | 8µs | 17µs | Class::Accessor::Grouped::BEGIN@88 |
| 1 | 1 | 1 | 7µs | 10µs | Class::Accessor::Grouped::BEGIN@3 |
| 1 | 1 | 1 | 4µs | 4µs | Class::Accessor::Grouped::BEGIN@8 |
| 1 | 1 | 1 | 4µs | 4µs | Class::Accessor::Grouped::BEGIN@5 |
| 1 | 1 | 1 | 4µs | 4µs | Class::Accessor::Grouped::BEGIN@6 |
| 1 | 1 | 1 | 4µs | 4µs | Class::Accessor::Grouped::BEGIN@4 |
| 1 | 1 | 1 | 3µs | 3µs | Class::Accessor::Grouped::BEGIN@23 |
| 2 | 2 | 1 | 2µs | 2µs | __CAG_ENV__::__ANON__ (xsub) |
| 0 | 0 | 0 | 0s | 0s | Class::Accessor::Grouped::CLONE |
| 0 | 0 | 0 | 0s | 0s | Class::Accessor::Grouped::__ANON__[:728] |
| 0 | 0 | 0 | 0s | 0s | Class::Accessor::Grouped::__ANON__[:748] |
| 0 | 0 | 0 | 0s | 0s | Class::Accessor::Grouped::__ANON__[:914] |
| 0 | 0 | 0 | 0s | 0s | Class::Accessor::Grouped::get_component_class |
| 0 | 0 | 0 | 0s | 0s | Class::Accessor::Grouped::get_simple |
| 0 | 0 | 0 | 0s | 0s | Class::Accessor::Grouped::make_group_ro_accessor |
| 0 | 0 | 0 | 0s | 0s | Class::Accessor::Grouped::make_group_wo_accessor |
| 0 | 0 | 0 | 0s | 0s | Class::Accessor::Grouped::mk_group_ro_accessors |
| 0 | 0 | 0 | 0s | 0s | Class::Accessor::Grouped::mk_group_wo_accessors |
| 0 | 0 | 0 | 0s | 0s | Class::Accessor::Grouped::set_component_class |
| 0 | 0 | 0 | 0s | 0s | Class::Accessor::Grouped::set_simple |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSet::__result_class_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSet::_result_source_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::__columns_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::__ordered_columns_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::__primaries_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::__relationships_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::__unique_constraints_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::_column_info_from_storage_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::_name_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::_resultset_attributes_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::_source_info_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::_source_name_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::column_info_from_storage |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::resultset_attributes |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::source_info |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSourceHandle::__detached_source_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSourceHandle::_detached_source |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSourceHandle::_schema_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSourceHandle::_source_moniker_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSourceHandle::schema |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSourceHandle::source_moniker |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Row::_in_storage_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Row::in_storage |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::SQLMaker::_limit_dialect_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::SQLMaker::_name_sep_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::SQLMaker::_quote_char_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::SQLMaker::limit_dialect |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::SQLMaker::name_sep |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::SQLMaker::quote_char |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::DBI::__autoinc_supplied_for_op_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::DBI::__conn_pid_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::DBI::__connect_info_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::DBI::__dbh_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::DBI::__dbh_autocommit_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::DBI::__dbh_details_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::DBI::__dbic_connect_attributes_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::DBI::__driver_determined_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::DBI::__perform_autoinc_retrieval_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::DBI::__sql_maker_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::DBI::__sql_maker_opts_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::DBI::_auto_savepoint_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::DBI::_autoinc_supplied_for_op |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::DBI::_disable_sth_caching_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::DBI::_on_connect_call_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::DBI::_on_connect_do_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::DBI::_on_disconnect_call_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::DBI::_on_disconnect_do_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::DBI::_perform_autoinc_retrieval |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::DBI::_unsafe_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::DBI::auto_savepoint |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::DBI::disable_sth_caching |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::DBI::on_disconnect_call |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::DBI::on_disconnect_do |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::_auto_savepoint_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::_debug_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::_savepoints_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::_schema_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::_transaction_depth_accessor |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::auto_savepoint |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::savepoints |
| 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 |