Perl 内嵌 C 代码
[i=s] 本帖最后由 523066680 于 2017-8-5 08:23 编辑 [/i]在优化猜数字游戏脚本的运行效率时(其实是在看Imager模块的示例偶然发现),发现了 Perl 可以内联 C 代码,可以极大地提高效率。
原本跑完5040次猜数字测试,用 perl 写的test函数消耗(累积)可能需要10秒,现在只需要零点几秒。[code]use IO::Handle;
use Inline C;
STDOUT->autoflush(1);
my $nums = "4109";
my $guess = "0124";
my $AB = "00";
for (1..5)
{
$AB = "00";
test($nums, $guess, $AB);
print "$AB\n";
}
__END__
__C__
void test(char *stra, char *strb, char *AB)
{
int idx;
for ( idx = 0; idx < 4; idx++ )
{
if ( stra[idx] == strb[idx] )
AB[0]++;
else
if ( strchr(stra, strb[idx]) != 0 )
{
AB[1]++;
}
}
}
[/code]不过以上代码有个问题,就是 $AB = "00" 的重置无效了,每次结果都会被递增,输出如下[code]12
24
36
48
5:[/code]所以C函数部分重写,用临时变量从 '0' 开始计数。(为了统一,我用的是字符'0' )[code]__END__
__C__
void bullcow(char *stra, char *strb, char *AB)
{
int idx;
char a = '0';
char b = '0';
for ( idx = 0; idx < 4; idx++ )
{
if ( stra[idx] == strb[idx] )
a++;
else
if ( strchr(stra, strb[idx]) != 0 )
{
b++;
}
}
AB[0] = a;
AB[1] = b;
}[/code] :o
__END__
写在最上面吗?这逻辑我没法懂啊。 [i=s] 本帖最后由 523066680 于 2017-8-5 14:44 编辑 [/i]
[b]回复 [url=http://bbs.bathome.net/redirect.php?goto=findpost&pid=201921&ptid=44936]2#[/url] [i]codegay[/i] [/b]
__END__ 在 perl 里面表示脚本结束的节点,可以放备注、数据之类的信息。
效率对比
[i=s] 本帖最后由 523066680 于 2017-8-5 09:08 编辑 [/i]时间占用对比,用 Devel::NYTProf 模块分析效率
perl -d:NYTProf normal.pl
nytprofhtml
[img]http://imgout.ph.126.net/57004002/01.jpg[/img]
perl -d:NYTProf InlineC.pl
nytprofhtml
[img]http://imgout.ph.126.net/57008002/02.jpg[/img]
两份完整的测试代码:[code]use IO::Handle;
STDOUT->autoflush(1);
my $nums = "4109";
my $guess = "0124";
my $AB = "00";
for ( 1 .. 100000 )
{
$AB = "00";
bullcow($nums, $guess, \$AB);
print "$AB\n";
}
sub bullcow
{
my ($nums, $guess, $AB) = @_;
my ($A, $B) = (0, 0);
my $t;
for my $i ( 0 .. 3 )
{
if ( substr($nums, $i, 1) eq substr($guess, $i, 1) )
{
$A++;
}
else
{
$t = substr($guess, $i, 1);
$B++ if ( $nums =~/$t/ );
}
}
$$AB = "$A$B";
}[/code]内联C的版本:[code]use Inline C;
use IO::Handle;
STDOUT->autoflush(1);
my $nums = "4109";
my $guess = "0124";
my $AB = "00";
for ( 1 .. 100000 )
{
$AB = "00";
bullcow($nums, $guess, $AB);
print "$AB\n";
}
__END__
__C__
void bullcow(char *stra, char *strb, char *AB)
{
int idx;
char a = '0';
char b = '0';
for ( idx = 0; idx < 4; idx++ )
{
if ( stra[idx] == strb[idx] )
a++;
else
if ( strchr(stra, strb[idx]) != 0 )
{
b++;
}
}
AB[0] = a;
AB[1] = b;
}[/code] 我对perl完全不懂哦。 提高效率啊。
页:
[1]