I wonder why nobody yet tried to write something like Class::MethodMaker in XS? I tried to compare pure Perl accessor methods and their XS analogs and the latest was noticibly faster. It would be very nice if we had a CPAN module which provides basic constuctor, accessor and other common methods implemented in XS so everybody could benefit from these speed gains in their Perl OO code without resorting to writting XS themselves.
use Class::XSMethodMaker
get_set => [qw(foo bar)];
Does this mean that XS code for foo() and bar() are generated and compiled on the fly? Or does it just do what Class::MethodMaker does and generate closures bound to *foo and *bar? Can you generate a closure in XS which closes around C code?
-sam
Re:Interesting idea
IlyaM on 2003-04-03T11:16:51
Tough question. One possible solution is pregenerating XS code given a list of fields. Another even generating C code on fly what should not be very hard using Inline::C. Anyway it doesn't seem a proper way to me and I'd like to be able simulate closures in C code. No idea how though. Not sure that it is even possible.
Or am I missing the point (or should that be the profile?) here?
-Dom
Re:Why are they faster?
IlyaM on 2003-04-03T11:08:09
Perl method dispatch is slow but perl code for accessors is not fast also. Here an example (one accessor is implemented in Perl and another in C with help of Inline::C):
use Benchmark;
my $obj = A->new;
$obj->field1('test');
$obj->field2('test');
timethese(1000000,
&nb sp; { pure_perl => sub { $obj->field1($obj->field1) },
inline_c => sub { $obj->field2($obj->field2) }
});
package A;
sub new { bless {}, shift }
sub field1 {
my $self = shift;
if(@_) {
$self->{field1} = $_[0];
}
return $self->{field1};
}
use Inline C => <<'END';
SV* field2 (SV* self,...) {
SV** temp;
Inline_Stack_Vars;
if(!(SvROK(self) && SvTYPE(SvRV(self)) == SVt_PVHV))
croak("Not a hash reference");
if(Inline_Stack_Items > 1) {
SV* value = Inline_Stack_Item(1);
if(! hv_store((HV*) SvRV(self), "field2", 6, SvREFCNT_inc(value), 0)) {
SvREFCNT_dec(value);
croak("Cannot store in hash");
}
}
if(temp = hv_fetch((HV*) SvRV(self), "field2", 6, 0)) {
return SvREFCNT_inc(*temp);
} else {
return &PL_sv_undef;
}
}
ENDResults on my computer:
Benchmark: timing 1000000 iterations of inline_c, pure_perl...
inline_c: 2 wallclock secs ( 2.25 usr + 0.00 sys = 2.25 CPU) @ 444444.44/s
(n=1000000)
pure_perl: 6 wallclock secs ( 6.67 usr + 0.05 sys = 6.72 CPU) @ 148809.52/s
(n=1000000)