Stopping Perl XS modules from silently falling back to pure-perl
It 开发者_开发知识库seems some (many?) modules on CPAN are partly implemented in C using XS, and can fall back to a pure-perl implementation if necessary. While this is smart, it can obviously hurt performance, and I would like to know it happens so I can fix the problem.
Is there a general way of stopping or detecting this type of fallback?
For an example of this behaviour take a look at the (very handy) Date::Simple (code snippet)
Any solution would have to be on a per module basis (because the decision on which implementation to use is made by the parent module itself, not some mechanism in Perl). In the case you cited, checking the value of $Date::Simple::NoXs after the use statement will tell you if XS is being used or not.
use Date::Simple;
die "not using XS for Date::Simple\n" if $Date::Simple::NoXs;
For instance, to detect if Scalar::Util is using the XS or pure Perl versions you have to check for the existence of the dualvar function.
use Scalar::Util;
die "not using XS for Scalar::Util\n" unless if @Scalar::Util::EXPORTFAIL;
This is a really good feature request. Unfortunately, short of what the module author has programmed, perl has no knowledge if the module has XS or Pure Perl (PP) variants and if the engine was loaded through fallback.
This example you bring up is compounded by the effect that they're packaged in the same distro and module, and it is all done internally. I'd patch it to follow the CPAN convention: DateSimple
, which requires DateSimple::PP
and recommends DateSimple::XS
. This is how Text::CSV
, and others do it. This method permits using the ::XS
constructor directly to force use of XS
and at the same time not even installing the pureperl variant. Alternatively, you can package them together -- this is what Template::Stash
does with Template::Stash::XS
. The first step to getting anything unified is getting the functionality ad-hoc.
This sort of thing could be easily done if the modules all pulled in a Moose::Role
that provided a few basic attributes _xs_class_name
, _pp_class_name
, and engine_override
. But, again, there is nothing as of now that even seeds a unified API to achieve this.
There is a general way to detect that your function is a XSUB CV. Just check if the XSUB slot of the CV returns a non-NULL pointer or not.
e.g. check for My::func
sub isxsub {
use B;
my $name = shift;
my $cv = B::svref_2object(\&$name);
return !!$cv->XSUB;
}
精彩评论