取势 明道 优术

perl 的调试和性能测试 4,355 views

作者为 扶 凯 发表

Perl 程序的调试,以前玩 php 都是 print, var_dump(), firebug 之类来调试.在 Perl 中,也有很多来方法我们调试的.在我看来调试分二种,一种是功能调试(排错之类保证功能完整).一种是性能调试.

功能调试

1. 最常用的方法

(1. print:这个用户就不用写了吧

(2. 模块: Data::Dumper
这个使用很容易,主要就是使用Dumper的函数做输出

#!/usr/bin/perl
use strict;
use Data::Dumper;

my $hash = {
        foo => 'test1',
        bar => {
            foo1 => 'test2',
                }
    };

print Dumper($hash);

这个会非常非常清楚的输出数据结构的信息:

$VAR1 = {
          'bar' => {
                     'foo1' => 'test2'
                   },
          'foo' => 'test1'
        };


(3 模块:Smart::Comments
这个模块就更加好用了,伟大的CPAN…..这个只需要###加上后面的变量就能输出变量中的信息.你可以在调试时打开,调试完了就关掉.超爽.

#!/usr/bin/perl
use strict;
use Smart::Comments;

my $hash = {
        foo => 'test1',
        bar => {
            foo1 => 'test2',
                }
    };

### hash: $hash 

见到上面###后面的内容没,这样很不错吧..这个更新清楚的打印出数据结构

### hash: {
###         bar => {
###                  foo1 => 'test2'
###                },
###         foo => 'test1'
###       }

4. 监控变化被谁修改 Scalar::Watcher

use Scalar::Watcher qw(when_modified when_destroyed);
 
{
  my $a = 123;
  $a = 456;
  when_modified $a, sub { 
      print "catch $_[0]\n" 
  };
  when_destroyed $a, sub { 
      print "destroy $_[0]\n" 
   };
  $a = 'oo';
  $a = 567;
 
  # then you'll get
  # catch oo
  # catch 567
  # destroy 567
}


(2 perl的调试器

perl -d yourperl.pl


   -s      Step 运行一行,跟踪进入子程序
   -n      Next 运行一行
   -r      Return 运行到当前子程序结束
   -p   变量名         查看变量
   -x   变量名         查看变量,友好格式(hash用引用)
   -l/-/w        列出前后的代码
   -c   行号          执行到"行号"
   -c             执行,直到遇到断点
   -b   行号          设置断点(b 子程序名)
   -b   行号 条件       设置条件断点
   -d   行号          去除"行号"处的断点
   -L   列出所有的断点
   -t    跟踪执行

(3 出错信号

这个不在详细写了.在我的另一个文章中,perl中的并发和信号中

性能调试

这个晚点在写困死了,其它下次写

(1. test模块

 

(2. Devel::Coverage模块

perl -d:Coverage yourperl.pl

这个主要可以测试到代码的覆盖范围.分支的运行情况.

(3. Devel::SmallProf模块

这个模块会生成非常不错的文本文件samllprof.out来显示各行运行的时间,真实时间和cpu时间.它的精度要求好些所以需要Time::HiRes这个模块.
 

perl -d:SmallProf yourperl.pl

暂时关闭和打开profile:

$DB::profile = 0;

这之间的代码不会被SmallProf跟踪

$DB::profile = 1;

指定要跟踪的模块名称,主程序用'main'表示,例如

use Data::Dumper;
use TK;
%DB::package = ('main' => 1,
                  'Data::Dumper' => 1);

只跟踪主程序和Data::Dumper的代码执行情况 不列出执行计数为0的行

$DB::drop_zeros = 1;

(4. Devel::DProf 模块来以函数为范围测试 Perl 程序的性能

perl -d:DProf yourperl.pl

这个和上面的作者大多相同,但这个会生成自己的格式文件,可以用它来画图之类.使用 dprofpp 来查看输出是怎么样的

$dprofpp tmon.out 
Total Elapsed Time = 2.447954 Seconds
  User+System Time = 2.437954 Seconds
Exclusive Times
%Time ExclSec CumulS #Calls sec/call Csec/c  Name
 88.1   2.149  2.164      1   2.1488 2.1645  main::parselog
 2.87   0.070  0.119     10   0.0070 0.0119  Spreadsheet::WriteExcel::Workbook:
                                             :BEGIN
 2.05   0.050  0.257     11   0.0045 0.0234  main::BEGIN
 1.23   0.030  0.149      8   0.0037 0.0186  Spreadsheet::WriteExcel::WorkbookB
                                             ig::BEGIN
 0.82   0.020  0.020     10   0.0020 0.0020  Spreadsheet::WriteExcel::Worksheet
                                             ::BEGIN
 0.82   0.020  0.020    154   0.0001 0.0001  Perl6::Junction::One::str_eq
 0.41   0.010  0.010      1   0.0100 0.0100  Smart::Comments::__ANON__
 0.41   0.010  0.010     11   0.0009 0.0009  DynaLoader::dl_find_symbol
 0.41   0.010  0.010      5   0.0020 0.0020  Perl6::Junction::BEGIN
 0.41   0.010  0.010      6   0.0017 0.0017  YAML::Syck::BEGIN
 0.41   0.010  0.010      5   0.0020 0.0020  IO::Seekable::BEGIN
 0.41   0.010  0.010      6   0.0017 0.0016  Encode::BEGIN
 0.41   0.010  0.020      5   0.0020 0.0039  Spreadsheet::WriteExcel::OLEwriter
                                             ::BEGIN
 0.41   0.010  0.020      6   0.0017 0.0033  Filter::Simple::BEGIN
 0.41   0.010  0.030     10   0.0010 0.0030  Smart::Comments::BEGIN

 

(5 Devel::FastProf

使用

perl -d:FastProf filename.pl

这个是需向行的,可以见到每行花的时间,需要输出测试的结果用 fprofpp -t 10, 输出如下

# fprofpp output format is:
# filename:line time count: source
CFDS/File.pm:321 4.44711 1321093: return $self->{block}{$bindex}{$pindex}{$key};
CFDS/File.pm:96 3.15971 1319500: if ( exists $fatchPool{$md5url}{$key} ){
/usr/local/share/perl/5.10.1/POE/Loop/Select.pm:199 3.00868 1633: my $hits = CORE::select(
CFDS/File.pm:94 2.47519 1319500: my ($md5url, $bindex, $pindex) = @_;
CFDS/File.pm:95 2.45544 1319500: my $key = $bindex . '|' . $pindex;
CFDS/File.pm:320 2.42175 1321093: my ($bindex, $pindex, $key) = @_;
CFDS/File.pm:275 2.40340 1319500: my $status       = $self->lookupFatchPool( $urlMD5, $bindex, $cursor );
CFDS/File.pm:274 2.37050 1319500: my $cursorStatus = $self->getByPiece($bindex, $cursor, 'data');
CFDS/File.pm:276 2.26949 1319500: next if $status or $cursorStatus;
CFDS/File.pm:319 2.20017 1321093: my $self = shift;

 

(6 Devel::NYTProf
目前非常值得推荐的测试用的模块,可以输出成 html.我们只要直接使用
perl -d:NYTProf /home/test.pl
来运行我们的程序,会在当前路径下生成 nytprof.out 这个文件 再用
nytprofhtml nytprof.out
生成 web 页面的目录,默认会生成在 nytprof 的目录,所以你需要使用 Web 软件来发布出来,象我这种懒人就使用 Plack 的单行来发布

plackup -MPlack::App::Directory -e 'Plack::App::Directory->new(root => "./nytprof");' -p 9988  --host xxx.xxx.xxx.xxx


用浏览器打开即可看到了

(6 DBI::Profile

测试DBI的,没用过…

在这几个 Perl 的性能测试模块中,分别是:

  1. Devel::DProf - 以函数为单位
  2. Devel::SmallProf - 以行为单位
  3. Devel::FastProf - 同上,但速度更快
  4. Benchmark – 检查指定代码块

来了就留个评论吧! 2个评论



    oliver 2014年04月25日 的 03:21

    Devel::Coverage这个模块怎么CPAN上都找不到???