300%? In my experience it's often a lot more than that!
That said, our old friend Class::XSAccessor to the rescue! If you're writing OO code, want lvalue accessors, and don't give a crap about validating incoming data, then its lvalue accessors are likely to be much faster than any pure Perl accessor you could write. (Not quite as fast as Class::XSAccessors non-lvalue accessors though.)
use v5.14;
use Benchmark qw(cmpthese);
package MyClass {
use Class::XSAccessor (
constructor => 'new',
lvalue_accessors => {
'lv_xs' => 'lv_xs',
},
accessors => {
'std_xs' => 'std_xs',
},
);
sub std {
$_[0]{std} = $_[1] if @_ > 1;
$_[0]{std};
}
sub lv_LV :lvalue {
use LV;
lvalue
set => sub { $_[0]{lv} = $_[1] if @_ > 1 },
get => sub { $_[0]{lv} },
}
sub lv :lvalue {
$_[0]{lv};
}
}
print LV->implementation, "\n";
cmpthese -3 => {
lv => q[
my $obj = MyClass->new;
$obj->lv = 0;
$obj->lv = $obj->lv + $_ for 1 .. 10_000;
],
lv_xs => q[
my $obj = MyClass->new;
$obj->lv_xs = 0;
$obj->lv_xs = $obj->lv_xs + $_ for 1 .. 10_000;
],
lv_LV => q[
my $obj = MyClass->new;
$obj->lv_LV = 0;
$obj->lv_LV = $obj->lv_LV + $_ for 1 .. 10_000;
],
std => q[
my $obj = MyClass->new;
$obj->std(0);
$obj->std($obj->std + $_) for 1 .. 10_000;
],
std_xs => q[
my $obj = MyClass->new;
$obj->std_xs(0);
$obj->std_xs($obj->std_xs + $_) for 1 .. 10_000;
],
};
__END__
LV::Backend::Sentinel
Rate lv_LV std lv lv_xs std_xs
lv_LV 2.51/s -- -87% -91% -95% -96%
std 19.8/s 690% -- -25% -58% -67%
lv 26.6/s 960% 34% -- -44% -55%
lv_xs 47.2/s 1784% 139% 78% -- -21%
std_xs 59.6/s 2275% 201% 124% 26% --
use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name