PerlでのMRO::Compatの__get_linear_isa_dfsが遅い件について
経緯:
なんかやたらクローンでまわしている処理が重いためNYTProfで計測しました。
分かったことがMRO::Compatの__get_linear_isa_dfsを何十万回と呼び出していました。
何回もMRO::Compatを呼んでいたのは、DBIx::Class::Rowのinflate_resultを利用して動的にRoleを追加していた点でした。
対象環境
perl: 5.8.9
Moose: 2.0202
MRO::Compat: 0.11
DBIx::Class: 0.08119
分かったこと
2、最終的にどうすれば分からないことが判明した。
1、MRO::Compatの__get_linear_isa_dfsはPerlのバージョンが5.009_005以下で呼ばれる。
メソッド解決順序について前回のブログとなんか繋がる内容ですね。
MRO-Compat-0.11/lib/MRO/Compat.pm
our $VERSION = '0.11'; BEGIN { # Alias our private functions over to # the mro:: namespace and load # Class::C3 if Perl < 5.9.5 if($] < 5.009_005) { $mro::VERSION # to fool Module::Install when generating META.yml = $VERSION; $INC{'mro.pm'} = __FILE__; *mro::import = \&__import; *mro::get_linear_isa = \&__get_linear_isa; *mro::set_mro = \&__set_mro; *mro::get_mro = \&__get_mro; *mro::get_isarev = \&__get_isarev; *mro::is_universal = \&__is_universal; *mro::method_changed_in = \&__method_changed_in; *mro::invalidate_all_method_caches = \&__invalidate_all_method_caches; require Class::C3; if($Class::C3::XS::VERSION && $Class::C3::XS::VERSION > 0.03) { *mro::get_pkg_gen = \&__get_pkg_gen_c3xs; } else { *mro::get_pkg_gen = \&__get_pkg_gen_pp; } } # Load mro.pm and provide no-op Class::C3::.*initialize() funcs for 5.9.5+ else { require mro; no warnings 'redefine'; *Class::C3::initialize = sub { 1 }; *Class::C3::reinitialize = sub { 1 }; *Class::C3::uninitialize = sub { 1 }; } }
sub __get_linear_isa_dfs { no strict 'refs'; my $classname = shift; my @lin = ($classname); my %stored; foreach my $parent (@{"$classname\::ISA"}) { print "$parent\n"; ##ここを追加 my $plin = __get_linear_isa_dfs($parent); foreach (@$plin) { next if exists $stored{$_}; push(@lin, $_); $stored{$_} = 1; } } return \@lin; }
以下結果です。
```
DBIx::Class::InflateColumn::DateTime
DBIx::Class::InflateColumn
DBIx::Class::Row
DBIx::Class::Componentised
Class::C3::Componentised
Class::Accessor::Grouped
DBIx::Class::Componentised
Class::C3::Componentised
Class::Accessor::Grouped
DBIx::Class::UUIDColumns
DBIx::Class::Componentised
Class::C3::Componentised
Class::Accessor::Grouped
DBIx::Class::Core
DBIx::Class::Relationship
DBIx::Class::Relationship::Helpers
DBIx::Class::Relationship::HasMany
DBIx::Class::Relationship::HasOne
DBIx::Class::Relationship::BelongsTo
DBIx::Class::Relationship::ManyToMany
DBIx::Class::Componentised
Class::C3::Componentised
Class::Accessor::Grouped
DBIx::Class::Relationship::Accessor
DBIx::Class::Relationship::CascadeActions
DBIx::Class::Relationship::ProxyMethods
DBIx::Class::Componentised
Class::C3::Componentised
Class::Accessor::Grouped
DBIx::Class::Relationship::Base
DBIx::Class::Componentised
Class::C3::Componentised
Class::Accessor::Grouped
DBIx::Class::Componentised
Class::C3::Componentised
Class::Accessor::Grouped
DBIx::Class::InflateColumn
DBIx::Class::Row
DBIx::Class::Componentised
Class::C3::Componentised
Class::Accessor::Grouped
DBIx::Class::PK::Auto
DBIx::Class::Componentised
Class::C3::Componentised
Class::Accessor::Grouped
DBIx::Class::PK
DBIx::Class::Row
DBIx::Class::Componentised
Class::C3::Componentised
Class::Accessor::Grouped
DBIx::Class::Row
DBIx::Class::Componentised
Class::C3::Componentised
Class::Accessor::Grouped
DBIx::Class::ResultSourceProxy::Table
DBIx::Class::ResultSourceProxy
DBIx::Class::Componentised
Class::C3::Componentised
Class::Accessor::Grouped
DBIx::Class::Componentised
Class::C3::Componentised
Class::Accessor::Grouped
Moose::Object
```
めっちゃDBIx::Class::ComponentisedとClass::C3::ComponentisedとClass::Accessor::Groupedを呼んでいる
次はさらに2回目のforeachも見てみました。
sub __get_linear_isa_dfs { no strict 'refs'; my $classname = shift; my @lin = ($classname); my %stored; foreach my $parent (@{"$classname\::ISA"}) { print "$parent\n"; ##ここを追加 my $plin = __get_linear_isa_dfs($parent); foreach (@$plin) { print "OYA:::$_\n"; ##ここを追加 next if exists $stored{$_}; push(@lin, $_); $stored{$_} = 1; } } return \@lin; }
```
Tachyon::Schema::Result
DBIx::Class::InflateColumn::DateTime
DBIx::Class::InflateColumn
DBIx::Class::Row
DBIx::Class::Componentised
Class::C3::Componentised
OYA:::Class::C3::Componentised
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
Class::Accessor::Grouped
OYA:::Class::Accessor::Grouped
OYA:::DBIx::Class
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
OYA:::Class::Accessor::Grouped
OYA:::DBIx::Class::Row
OYA:::DBIx::Class
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
OYA:::Class::Accessor::Grouped
OYA:::DBIx::Class::InflateColumn
OYA:::DBIx::Class::Row
OYA:::DBIx::Class
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
OYA:::Class::Accessor::Grouped
DBIx::Class::Componentised
Class::C3::Componentised
OYA:::Class::C3::Componentised
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
Class::Accessor::Grouped
OYA:::Class::Accessor::Grouped
OYA:::DBIx::Class
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
OYA:::Class::Accessor::Grouped
OYA:::DBIx::Class::InflateColumn::DateTime
OYA:::DBIx::Class::InflateColumn
OYA:::DBIx::Class::Row
OYA:::DBIx::Class
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
OYA:::Class::Accessor::Grouped
DBIx::Class::UUIDColumns
DBIx::Class::Componentised
Class::C3::Componentised
OYA:::Class::C3::Componentised
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
Class::Accessor::Grouped
OYA:::Class::Accessor::Grouped
OYA:::DBIx::Class
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
OYA:::Class::Accessor::Grouped
OYA:::DBIx::Class::UUIDColumns
OYA:::DBIx::Class
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
OYA:::Class::Accessor::Grouped
DBIx::Class::Core
DBIx::Class::Relationship
DBIx::Class::Relationship::Helpers
DBIx::Class::Relationship::HasMany
OYA:::DBIx::Class::Relationship::HasMany
DBIx::Class::Relationship::HasOne
OYA:::DBIx::Class::Relationship::HasOne
DBIx::Class::Relationship::BelongsTo
OYA:::DBIx::Class::Relationship::BelongsTo
DBIx::Class::Relationship::ManyToMany
OYA:::DBIx::Class::Relationship::ManyToMany
DBIx::Class::Componentised
Class::C3::Componentised
OYA:::Class::C3::Componentised
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
Class::Accessor::Grouped
OYA:::Class::Accessor::Grouped
OYA:::DBIx::Class
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
OYA:::Class::Accessor::Grouped
OYA:::DBIx::Class::Relationship::Helpers
OYA:::DBIx::Class::Relationship::HasMany
OYA:::DBIx::Class::Relationship::HasOne
OYA:::DBIx::Class::Relationship::BelongsTo
OYA:::DBIx::Class::Relationship::ManyToMany
OYA:::DBIx::Class
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
OYA:::Class::Accessor::Grouped
DBIx::Class::Relationship::Accessor
OYA:::DBIx::Class::Relationship::Accessor
DBIx::Class::Relationship::CascadeActions
OYA:::DBIx::Class::Relationship::CascadeActions
DBIx::Class::Relationship::ProxyMethods
DBIx::Class::Componentised
Class::C3::Componentised
OYA:::Class::C3::Componentised
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
Class::Accessor::Grouped
OYA:::Class::Accessor::Grouped
OYA:::DBIx::Class
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
OYA:::Class::Accessor::Grouped
OYA:::DBIx::Class::Relationship::ProxyMethods
OYA:::DBIx::Class
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
OYA:::Class::Accessor::Grouped
DBIx::Class::Relationship::Base
DBIx::Class::Componentised
Class::C3::Componentised
OYA:::Class::C3::Componentised
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
Class::Accessor::Grouped
OYA:::Class::Accessor::Grouped
OYA:::DBIx::Class
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
OYA:::Class::Accessor::Grouped
OYA:::DBIx::Class::Relationship::Base
OYA:::DBIx::Class
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
OYA:::Class::Accessor::Grouped
DBIx::Class::Componentised
Class::C3::Componentised
OYA:::Class::C3::Componentised
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
Class::Accessor::Grouped
OYA:::Class::Accessor::Grouped
OYA:::DBIx::Class
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
OYA:::Class::Accessor::Grouped
OYA:::DBIx::Class::Relationship
OYA:::DBIx::Class::Relationship::Helpers
OYA:::DBIx::Class::Relationship::HasMany
OYA:::DBIx::Class::Relationship::HasOne
OYA:::DBIx::Class::Relationship::BelongsTo
OYA:::DBIx::Class::Relationship::ManyToMany
OYA:::DBIx::Class
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
OYA:::Class::Accessor::Grouped
OYA:::DBIx::Class::Relationship::Accessor
OYA:::DBIx::Class::Relationship::CascadeActions
OYA:::DBIx::Class::Relationship::ProxyMethods
OYA:::DBIx::Class::Relationship::Base
DBIx::Class::InflateColumn
DBIx::Class::Row
DBIx::Class::Componentised
Class::C3::Componentised
OYA:::Class::C3::Componentised
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
Class::Accessor::Grouped
OYA:::Class::Accessor::Grouped
OYA:::DBIx::Class
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
OYA:::Class::Accessor::Grouped
OYA:::DBIx::Class::Row
OYA:::DBIx::Class
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
OYA:::Class::Accessor::Grouped
OYA:::DBIx::Class::InflateColumn
OYA:::DBIx::Class::Row
OYA:::DBIx::Class
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
OYA:::Class::Accessor::Grouped
DBIx::Class::PK::Auto
DBIx::Class::Componentised
Class::C3::Componentised
OYA:::Class::C3::Componentised
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
Class::Accessor::Grouped
OYA:::Class::Accessor::Grouped
OYA:::DBIx::Class
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
OYA:::Class::Accessor::Grouped
OYA:::DBIx::Class::PK::Auto
OYA:::DBIx::Class
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
OYA:::Class::Accessor::Grouped
DBIx::Class::PK
DBIx::Class::Row
DBIx::Class::Componentised
Class::C3::Componentised
OYA:::Class::C3::Componentised
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
Class::Accessor::Grouped
OYA:::Class::Accessor::Grouped
OYA:::DBIx::Class
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
OYA:::Class::Accessor::Grouped
OYA:::DBIx::Class::Row
OYA:::DBIx::Class
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
OYA:::Class::Accessor::Grouped
OYA:::DBIx::Class::PK
OYA:::DBIx::Class::Row
OYA:::DBIx::Class
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
OYA:::Class::Accessor::Grouped
DBIx::Class::Row
DBIx::Class::Componentised
Class::C3::Componentised
OYA:::Class::C3::Componentised
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
Class::Accessor::Grouped
OYA:::Class::Accessor::Grouped
OYA:::DBIx::Class
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
OYA:::Class::Accessor::Grouped
OYA:::DBIx::Class::Row
OYA:::DBIx::Class
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
OYA:::Class::Accessor::Grouped
DBIx::Class::ResultSourceProxy::Table
DBIx::Class::ResultSourceProxy
DBIx::Class::Componentised
Class::C3::Componentised
OYA:::Class::C3::Componentised
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
Class::Accessor::Grouped
OYA:::Class::Accessor::Grouped
OYA:::DBIx::Class
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
OYA:::Class::Accessor::Grouped
OYA:::DBIx::Class::ResultSourceProxy
OYA:::DBIx::Class
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
OYA:::Class::Accessor::Grouped
OYA:::DBIx::Class::ResultSourceProxy::Table
OYA:::DBIx::Class::ResultSourceProxy
OYA:::DBIx::Class
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
OYA:::Class::Accessor::Grouped
DBIx::Class::Componentised
Class::C3::Componentised
OYA:::Class::C3::Componentised
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
Class::Accessor::Grouped
OYA:::Class::Accessor::Grouped
OYA:::DBIx::Class
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
OYA:::Class::Accessor::Grouped
OYA:::DBIx::Class::Core
OYA:::DBIx::Class::Relationship
OYA:::DBIx::Class::Relationship::Helpers
OYA:::DBIx::Class::Relationship::HasMany
OYA:::DBIx::Class::Relationship::HasOne
OYA:::DBIx::Class::Relationship::BelongsTo
OYA:::DBIx::Class::Relationship::ManyToMany
OYA:::DBIx::Class
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
OYA:::Class::Accessor::Grouped
OYA:::DBIx::Class::Relationship::Accessor
OYA:::DBIx::Class::Relationship::CascadeActions
OYA:::DBIx::Class::Relationship::ProxyMethods
OYA:::DBIx::Class::Relationship::Base
OYA:::DBIx::Class::InflateColumn
OYA:::DBIx::Class::Row
OYA:::DBIx::Class::PK::Auto
OYA:::DBIx::Class::PK
OYA:::DBIx::Class::ResultSourceProxy::Table
OYA:::DBIx::Class::ResultSourceProxy
OYA:::Tachyon::Schema::Result
OYA:::DBIx::Class::InflateColumn::DateTime
OYA:::DBIx::Class::InflateColumn
OYA:::DBIx::Class::Row
OYA:::DBIx::Class
OYA:::DBIx::Class::Componentised
OYA:::Class::C3::Componentised
OYA:::Class::Accessor::Grouped
OYA:::DBIx::Class::UUIDColumns
OYA:::DBIx::Class::Core
OYA:::DBIx::Class::Relationship
OYA:::DBIx::Class::Relationship::Helpers
OYA:::DBIx::Class::Relationship::HasMany
OYA:::DBIx::Class::Relationship::HasOne
OYA:::DBIx::Class::Relationship::BelongsTo
OYA:::DBIx::Class::Relationship::ManyToMany
OYA:::DBIx::Class::Relationship::Accessor
OYA:::DBIx::Class::Relationship::CascadeActions
OYA:::DBIx::Class::Relationship::ProxyMethods
OYA:::DBIx::Class::Relationship::Base
OYA:::DBIx::Class::PK::Auto
OYA:::DBIx::Class::PK
OYA:::DBIx::Class::ResultSourceProxy::Table
OYA:::DBIx::Class::ResultSourceProxy
Moose::Object
OYA:::Moose::Object
$VAR1 = [
'Tachyon::Schema::Result::Campaign',
'Tachyon::Schema::Result',
'DBIx::Class::InflateColumn::DateTime',
'DBIx::Class::InflateColumn',
'DBIx::Class::Row',
'DBIx::Class',
'DBIx::Class::Componentised',
'Class::C3::Componentised',
'Class::Accessor::Grouped',
'DBIx::Class::UUIDColumns',
'DBIx::Class::Core',
'DBIx::Class::Relationship',
'DBIx::Class::Relationship::Helpers',
'DBIx::Class::Relationship::HasMany',
'DBIx::Class::Relationship::HasOne',
'DBIx::Class::Relationship::BelongsTo',
'DBIx::Class::Relationship::ManyToMany',
'DBIx::Class::Relationship::Accessor',
'DBIx::Class::Relationship::CascadeActions',
'DBIx::Class::Relationship::ProxyMethods',
'DBIx::Class::Relationship::Base',
'DBIx::Class::PK::Auto',
'DBIx::Class::PK',
'DBIx::Class::ResultSourceProxy::Table',
'DBIx::Class::ResultSourceProxy',
'Moose::Object'
];
```