标题: [原创教程] Perl 内嵌 C 代码 [打印本页]
作者: 523066680 时间: 2017-8-4 22:25 标题: Perl 内嵌 C 代码
本帖最后由 523066680 于 2017-8-5 08:23 编辑
在优化猜数字游戏脚本的运行效率时(其实是在看Imager模块的示例偶然发现),发现了 Perl 可以内联 C 代码,可以极大地提高效率。
原本跑完5040次猜数字测试,用 perl 写的test函数消耗(累积)可能需要10秒,现在只需要零点几秒。- 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]++;
- }
- }
- }
复制代码
不过以上代码有个问题,就是 $AB = "00" 的重置无效了,每次结果都会被递增,输出如下复制代码
所以C函数部分重写,用临时变量从 '0' 开始计数。(为了统一,我用的是字符'0' )- __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;
- }
复制代码
作者: codegay 时间: 2017-8-5 01:47
__END__
写在最上面吗?这逻辑我没法懂啊。
作者: 523066680 时间: 2017-8-5 08:08
本帖最后由 523066680 于 2017-8-5 14:44 编辑
回复 2# codegay
__END__ 在 perl 里面表示脚本结束的节点,可以放备注、数据之类的信息。
作者: 523066680 时间: 2017-8-5 08:57 标题: 效率对比
本帖最后由 523066680 于 2017-8-5 09:08 编辑
时间占用对比,用 Devel::NYTProf 模块分析效率
perl -d:NYTProf normal.pl
nytprofhtml
perl -d:NYTProf InlineC.pl
nytprofhtml
两份完整的测试代码:- 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";
- }
复制代码
内联C的版本:- 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;
- }
复制代码
作者: codegay 时间: 2017-8-5 14:40
我对perl完全不懂哦。
作者: Wiki 时间: 2018-9-23 00:10
提高效率啊。
欢迎光临 批处理之家 (http://bathome.net./) |
Powered by Discuz! 7.2 |