碎碎碎碎屁

Archive for 四月, 2013

从str2time开始的优化

by on 4月.07, 2013, under ,

线上有个perl的脚本,准实时(1分钟cron着)的跑着,一般一跑要1分多钟。之前初看还以为是sql设计差、脚本变量都是全局等等问题,后来想想不行,得用数据说话,于是找到了传说中的nytprof。安装据说要先装下JSON::Any,再装Devel::NYTProf;用的时候perl -d:NYTProf ./a.pl,再nytprofhtml nytprof.out下,好了现在只要w3m nytprof/index.html就能看到详细了。

不看不知道,一看吓一跳,最前面耗时最长的居然都是Date::Parse、Time::Local,而main、DBI这些原以为会慢的差前面两个Date、Time一个数量级啊。那今天就把目光放在Date::Parse里,仔细看了脚本,其实就是用到了str2time,把形如”2013-04-07 22:22:22″的转化为那个秒数。我们这个脚本大概执行一次会用到50多万次的str2time。

网上翻了翻说是Date::Parse慢,于是换了个Time::ParseDate,测试用例如下:
#1.pl
use Date::Parse;
my $start = "2013-04-08 02:00:00";
my $end = "2013-04-08 03:00:00";
for (my $i = 0; $i < 100000; $i++)
{ print str2time($start),"\n",str2time($end),"\n";}
#2.pl
use Time::ParseDate;
my $start = "2013-04-08 02:00:00";
my $end = "2013-04-08 03:00:00";
for (my $i = 0; $i < 100000; $i++)
{ print parsedate($start),"\n",parsedate($end),"\n";}

time比较出来的时间是从原来的13秒变成9秒,稍有提高。

期间多次strace发现经常会访问/etc/localtime,怀疑是模块里不论何时都要去算下现在时间引起的,遂决定直接用timelocal这个最基本的命令传入年月日时分秒来计算。
#3.pl
use Time::Local;
sub new() {
$_ = @_[0];
my( $Y,$M,$D,$h,$m,$s ) = /(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/;
return timelocal($s,$m,$h,$D,$M-1,$Y);
}
my $start = "2013-04-08 02:00:00";
my $end = "2013-04-08 03:00:00";
for (my $i = 0; $i < 100000; $i++)
{ print &new($start),"\n",&new($end),"\n";}

于2.pl的耗时比较,从9秒降到6秒多。

strace里还是能看到访问/etc/localtime,在Time::Local里看到还有timegm,试试
> return timelocal($s,$m,$h,$D,$M-1,$Y);
< return timegm($s,$m,$h,$D,$M-1,$Y)-28800;

由于并不牵涉时区,遂直接写死在里面。瞬间,从6秒多降到2秒内,和最开始比已经下降了一个数量级了。所以那,调用次数高的函数啊一定要好好调教下~

把这个提给原脚本owner后发现,原脚本只是为了比较两个时间string转后的大小。他直接改成
> return timegm($s,$m,$h,$D,$M-1,$Y)-28800;
< return ($Y*366*24*3600 + $M*31*24*3600 + $D*24*3600 + $h*3600 + $m*60 + $s);

来进行比较。时间差不多从2秒内变为1秒内。

然后洗澡时候忽然想起别人说过笑话,数据库存时间直接用string存20130407222222,于是测试这样比大小。
sub new() {
$a = @_[0];
$a =~ tr/ \-://d ;
return $a;
}
my $start = "2013-04-08 02:00:00";
my $end = "2013-04-08 03:00:00";
for (my $i = 0; $i < 1000000; $i++)
{ if (&new($start) < &new($end)){print 1};}

测试用例上提高一个数量级跑,上一种7秒多,这一种2秒多。
#p.s.用=~ s/\-|\s*|\://g;代替=~ tr/ \-://d;会比上一段所说的还要慢
也就是说,最开始13秒的,现在已经变成0.2秒了,所以那,优化逻辑也很重要~

改了之后load下降

Leave a Comment :, more...