Moose对象似乎是带有成员变量作为条目的祝福hashrefs。使用哈希语法访问成员是否安全?我想要的只是获取/设置成员变量的简单能力,但我发现perl生成的访问器的速度对于我的应用程序来说是不可接受的,直到我考虑在非驼鹿OO中重写它。是的,我知道优化是一种可以判处死刑的罪行,但我有一个十亿+行文件并添加一个简单的行计数器变量可以增加十亿+函数调用,这可以在一次运行中增加几小时。
显示慢度(100x)的示例:
package Bullwinkle;
use strict;
use warnings;
use Moose;
has 'x' => (is => 'rw', default => 0);
# counter is also slow
has 'counter' => (
traits => ['Counter'],
is => 'ro',
isa => 'Num',
default => 0,
handles => {
inc_counter => 'inc',
},
);
package main;
use strict;
use warnings;
use Benchmark qw/timethese cmpthese/;
my $bull = Bullwinkle->new();
my $hash = { x => 0 };
cmpthese(-1,{
bull => sub{
$bull->x(1 + $bull->x());
},
bull_direct => sub{
++$bull->{x}
},
bull_counter => sub{
$bull->inc_counter();
},
hash => sub{
++$hash->{x}
},
});
Rate bull bull_counter hash bull_direct bull 983040/s -- -28% -91% -92% bull_counter 1362629/s 39% -- -88% -88% hash 11251965/s 1045% 726% -- -3% bull_direct 11650844/s 1085% 755% 4% --
答案 0 :(得分:14)
我会说打破封装是不安全的,不管是不是。
请注意,您的bull
测试速度不会慢100倍。请记住,它使用了两次访问器。就在信封的背面,它从每秒1,000,000次运行到每秒2,000,000次访问。与哈希相比,这使得它大约为6倍。添加一堆这些减速并且它可以加起来。
然而,我不认为穆斯是那里的问题。当我尝试使用非Moose类来做同样的事情时,结果并没有那么好。看起来大多数减速只是来自正常的面向对象的方法调用。使用inc_counter
的非驼鹿和驼鹿类之间的差异大约为2倍。
基准是非常棘手的事情。您真的需要努力梳理不同的部件,并确保您测试适当的基本情况。当你得到狂野的数字时,你应该从怀疑论者开始并调整一下,直到它们不那么狂野。例如,即使Moose很慢,我也不认为如果你推测它很慢的话就会使用它。稍微慢一点,订单或数量是另一回事。
我对基准测试也很好奇,我想用make_immutable
来尝试。这是我在运行Lion的Mac Pro上使用Moose-2.0403的默认Perl5.14.2的结果。 Bull是你的原始代码,Rocky使用make_immutable
,而Natasha是非Moose类,它做同样的事情:
Rate bull rocky natasha bull_counter rocky_counter natasha_x rocky_x bull_x natasha_counter rocky_direct bull_direct natasha_direct hash
bull 728177/s -- -6% -17% -42% -43% -65% -66% -67% -71% -93% -94% -94% -95%
rocky 771011/s 6% -- -12% -39% -39% -63% -64% -65% -70% -93% -93% -94% -95%
natasha 877713/s 21% 14% -- -30% -31% -58% -59% -60% -66% -92% -92% -93% -94%
bull_counter 1260308/s 73% 63% 44% -- -1% -40% -42% -42% -51% -88% -89% -89% -91%
rocky_counter 1274310/s 75% 65% 45% 1% -- -39% -41% -42% -50% -88% -89% -89% -91%
natasha_x 2105717/s 189% 173% 140% 67% 65% -- -3% -4% -17% -81% -81% -82% -85%
rocky_x 2163925/s 197% 181% 147% 72% 70% 3% -- -1% -15% -80% -81% -82% -85%
bull_x 2184533/s 200% 183% 149% 73% 71% 4% 1% -- -14% -80% -80% -82% -85%
natasha_counter 2548621/s 250% 231% 190% 102% 100% 21% 18% 17% -- -77% -77% -79% -82%
rocky_direct 10901037/s 1397% 1314% 1142% 765% 755% 418% 404% 399% 328% -- -3% -9% -24%
bull_direct 11202734/s 1438% 1353% 1176% 789% 779% 432% 418% 413% 340% 3% -- -6% -21%
natasha_direct 11939231/s 1540% 1449% 1260% 847% 837% 467% 452% 447% 368% 10% 7% -- -16%
hash 14252488/s 1857% 1749% 1524% 1031% 1018% 577% 559% 552% 459% 31% 27% 19% --
这是我的计划:
#!/Users/brian/bin/perls/perl5.14.2
use v5.10.1;
use strict;
use warnings;
use Benchmark qw/timethese cmpthese/;
package Bullwinkle {
use strict;
use warnings;
use Moose;
has 'x' => (is => 'rw', default => 0);
# counter is also slow
has 'counter' => (
traits => ['Counter'],
is => 'ro',
isa => 'Num',
default => 0,
handles => {
inc_counter => 'inc',
},
);
}
package Rocky {
use strict;
use warnings;
use Moose;
has 'x' => (is => 'rw', default => 0);
# counter is also slow
has 'counter' => (
traits => ['Counter'],
is => 'ro',
isa => 'Num',
default => 0,
handles => {
inc_counter => 'inc',
},
);
__PACKAGE__->meta->make_immutable;
}
package Natasha {
use strict;
use warnings;
sub new { bless { 'x' => 0 }, $_[0] }
sub inc_counter { $_[0]->{x} += 1 }
sub x {
if( defined $_[1] ) { $_[0]->{x} = $_[1] }
else { $_[0]->{x} }
}
}
my $bull = Bullwinkle->new;
my $rocky = Rocky->new;
my $natasha = Natasha->new;
my $hash = { 'x' => 0 };
cmpthese(-1,{
bull => sub { $bull->x(1 + $bull->x ) },
bull_x => sub { $bull->x },
bull_direct => sub { ++$bull->{'x'} },
bull_counter => sub { $bull->inc_counter },
rocky => sub { $rocky->x(1 + $rocky->x ) },
rocky_x => sub { $rocky->x },
rocky_direct => sub { ++$rocky->{'x'} },
rocky_counter => sub { $rocky->inc_counter },
natasha => sub { $natasha->x(1 + $natasha->x ) },
natasha_x => sub { $natasha->x },
natasha_direct => sub { ++$natasha->{'x'} },
natasha_counter => sub { $natasha->inc_counter },
hash => sub { ++$hash->{'x'} },
});
答案 1 :(得分:0)
我认为这个基准测试还应该考虑以旧方式编写Perl类的“通常”方式:即使用$ self变量。
在这种情况下,公牛的好转率提高了3%,而且多头提高了12%。
以下是原始结果:
Rate tatiana bull rocky natasha bull_counter rocky_counter tatiana_x tatiana_counter bull_x natasha_x rocky_x natasha_counter bull_direct hash tatiana_direct rocky_direct natasha_direct
tatiana 785983/s -- -3% -11% -20% -35% -37% -55% -61% -66% -67% -67% -68% -94% -95% -95% -95% -95%
bull 811471/s 3% -- -8% -17% -33% -34% -54% -60% -65% -66% -66% -67% -94% -94% -94% -94% -95%
rocky 882215/s 12% 9% -- -10% -27% -29% -50% -56% -62% -63% -63% -64% -93% -94% -94% -94% -94%
natasha 983039/s 25% 21% 11% -- -18% -21% -44% -51% -58% -58% -59% -60% -93% -93% -93% -93% -94%
bull_counter 1203020/s 53% 48% 36% 22% -- -3% -31% -40% -48% -49% -50% -50% -91% -92% -92% -92% -92%
rocky_counter 1238753/s 58% 53% 40% 26% 3% -- -29% -39% -47% -48% -49% -49% -91% -91% -91% -91% -92%
tatiana_x 1747627/s 122% 115% 98% 78% 45% 41% -- -13% -25% -26% -28% -28% -87% -88% -88% -88% -89%
tatiana_counter 2016491/s 157% 148% 129% 105% 68% 63% 15% -- -13% -15% -16% -17% -85% -86% -86% -86% -87%
bull_x 2316929/s 195% 186% 163% 136% 93% 87% 33% 15% -- -2% -4% -5% -82% -84% -84% -84% -85%
natasha_x 2360644/s 200% 191% 168% 140% 96% 91% 35% 17% 2% -- -2% -3% -82% -83% -84% -84% -85%
rocky_x 2414483/s 207% 198% 174% 146% 101% 95% 38% 20% 4% 2% -- -1% -82% -83% -83% -83% -85%
natasha_counter 2429401/s 209% 199% 175% 147% 102% 96% 39% 20% 5% 3% 1% -- -81% -83% -83% -83% -85%
bull_direct 13107199/s 1568% 1515% 1386% 1233% 990% 958% 650% 550% 466% 455% 443% 440% -- -8% -10% -10% -17%
hash 14298763/s 1719% 1662% 1521% 1355% 1089% 1054% 718% 609% 517% 506% 492% 489% 9% -- -2% -2% -10%
tatiana_direct 14563556/s 1753% 1695% 1551% 1381% 1111% 1076% 733% 622% 529% 517% 503% 499% 11% 2% -- -0% -8%
rocky_direct 14563556/s 1753% 1695% 1551% 1381% 1111% 1076% 733% 622% 529% 517% 503% 499% 11% 2% 0% -- -8%
natasha_direct 15827561/s 1914% 1850% 1694% 1510% 1216% 1178% 806% 685% 583% 570% 556% 552% 21% 11% 9% 9% --
新测试用例的差异(注意新的Tatiana类):
--- bench.old 2012-04-15 19:29:55.000000000 +0200
+++ bench.pl 2012-04-15 19:17:25.000000000 +0200
@@ -57,9 +57,26 @@
}
}
+package Tatiana {
+ use strict;
+ use warnings;
+
+ sub new { bless { 'x' => 0 }, $_[0] }
+ sub inc_counter {
+ my $self = shift ;
+ $self->{x} += 1
+ }
+ sub x {
+ my ($self,$arg) = @_ ;
+ if( defined $arg ) { $self->{x} = $arg }
+ else { $self->{x} }
+ }
+ }
+
my $bull = Bullwinkle->new;
my $rocky = Rocky->new;
my $natasha = Natasha->new;
+my $tatiana = Tatiana->new;
my $hash = { 'x' => 0 };
@@ -79,5 +96,10 @@
natasha_direct => sub { ++$natasha->{'x'} },
natasha_counter => sub { $natasha->inc_counter },
+ tatiana => sub { $tatiana->x(1 + $tatiana->x ) },
+ tatiana_x => sub { $tatiana->x },
+ tatiana_direct => sub { ++$tatiana->{'x'} },
+ tatiana_counter => sub { $tatiana->inc_counter },
+
hash => sub { ++$hash->{'x'} },
});
希望这有帮助