<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>idv2 &#187; performance</title>
	<atom:link href="http://tech.idv2.com/tag/performance/feed/" rel="self" type="application/rss+xml" />
	<link>http://tech.idv2.com</link>
	<description>关注Web开发技术，关注Internet。</description>
	<lastBuildDate>Tue, 27 Jul 2010 12:54:54 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>[Perl]使用DProf测定程序执行效率</title>
		<link>http://tech.idv2.com/2008/10/30/perl-dprof/</link>
		<comments>http://tech.idv2.com/2008/10/30/perl-dprof/#comments</comments>
		<pubDate>Thu, 30 Oct 2008 06:52:04 +0000</pubDate>
		<dc:creator>charlee</dc:creator>
				<category><![CDATA[perl]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[tuning]]></category>

		<guid isPermaLink="false">http://tech.idv2.com/2008/10/30/perl-dprof/</guid>
		<description><![CDATA[<!-- begin Pukiwiki generated code--><p>代码写多了，程序就会变得臃肿；程序臃肿了，就会变慢。
这时提高代码执行效率就非常重要了。
但是，代码优化并不是几条best practice就能完成的。
那些无关痛痒的空间分配、减少复制等优化措施，虽然有效，但却微乎其微。
优化的关键，是要<strong>找出瓶颈并解决之</strong>，这样才能以最小的代价获得最佳的效果。</p>
<p>这就用到Perl的一个强大的工具：DProf。
它可以测定程序执行的每个函数所花费的时间，
通过它，你可以迅速找到瓶颈在什么地方，再对症下药。</p>
<p>最近我做的一次性能分析是这样的。
我们的系统在某种条件下发送邮件时特别慢，
甚至等待十几分钟也无法结束。究竟问题出在哪里却不得而知。
于是DProf上场了。</p>
<p>首先写了个脚本，专门调用发送邮件的功能，排除其他功能的影响。
然后运行命令：</p>
<pre>$ perl -d:DProf ./sendmail.pl</pre>
<p>运行结束之后，会在当前目录下生成一个tmon.out文件。
使用dprofpp即可查看统计信息：</p>
<pre>$ dprofpp
Total Elapsed Time = 19.70195 Seconds
 User+System Time = 18.52195 Seconds
Exclusive Times
%Time ExclSec CumulS #Calls sec/call Csec/c  Name
 83.5   15.46 15.770     11   1.4059 1.4337  Foo::Bar::crypt
 9.34   1.730  1.730      2   0.8650 0.8650  Net::Cmd::datasend
 1.24   0.230  0.305  17459   0.0000 0.0000  Crypt::Blowfish::encrypt
 0.70   0.129  0.818     36   0.0036 0.0227  base::import
 0.59   0.110  0.709     24   0.0046 0.0296  Foo::Bar::FooBarList::BEGIN
 0.44   0.082  0.082   9108   0.0000 0.0000  IO::Wrap::read
 0.40   0.075  0.075  17647   0.0000 0.0000  Crypt::Blowfish::crypt
 0.27   0.050  0.887      7   0.0071 0.1268  main::BEGIN</pre>
<p>统计信息的意思分别是：</p>
<ul class="list1" style="padding-left:16px;margin-left:16px"><li>ExclSec: 函数自身的执行时间（不包括函数调用的其他函数）</li>
<li>CumulS: 函数的执行时间（包括函数调用的其他函数）</li>
<li>#Calls: 调用次数</li>
<li>sec/call: ExceSec/#Calls</li>
<li>Csec/c: CumulS/#Calls</li>
<li>Name: 函数名称</li></ul>
<p>从上面的统计信息中可以看出，Foo::Bar::crypt占用了最多的时间(83.5%)。
而且更为重要的信息是，CumulS - ExclSec = 15.770 - 15.46 = 0.31，
也就是说，绝大部分时间都耗在了 Foo::Bar::crypt 函数本身，而不是它调用的其他函数。
这样，只需针对Foo::Bar::crypt函数进行分析就可以了。</p>
<p>还可以使用另一个性能测试工具<a href="http://tech.idv2.com/2006/10/03/perl-benchmark-by-devel-smallprof/">Devel::SmallProf</a>。</p>
<!-- end Pukiwiki generated code-->

]]></description>
			<content:encoded><![CDATA[<!-- begin Pukiwiki generated code--><p>代码写多了，程序就会变得臃肿；程序臃肿了，就会变慢。
这时提高代码执行效率就非常重要了。
但是，代码优化并不是几条best practice就能完成的。
那些无关痛痒的空间分配、减少复制等优化措施，虽然有效，但却微乎其微。
优化的关键，是要<strong>找出瓶颈并解决之</strong>，这样才能以最小的代价获得最佳的效果。</p>
<p>这就用到Perl的一个强大的工具：DProf。
它可以测定程序执行的每个函数所花费的时间，
通过它，你可以迅速找到瓶颈在什么地方，再对症下药。</p>
<p>最近我做的一次性能分析是这样的。
我们的系统在某种条件下发送邮件时特别慢，
甚至等待十几分钟也无法结束。究竟问题出在哪里却不得而知。
于是DProf上场了。</p>
<p>首先写了个脚本，专门调用发送邮件的功能，排除其他功能的影响。
然后运行命令：</p>
<pre>$ perl -d:DProf ./sendmail.pl</pre>
<p>运行结束之后，会在当前目录下生成一个tmon.out文件。
使用dprofpp即可查看统计信息：</p>
<pre>$ dprofpp
Total Elapsed Time = 19.70195 Seconds
 User+System Time = 18.52195 Seconds
Exclusive Times
%Time ExclSec CumulS #Calls sec/call Csec/c  Name
 83.5   15.46 15.770     11   1.4059 1.4337  Foo::Bar::crypt
 9.34   1.730  1.730      2   0.8650 0.8650  Net::Cmd::datasend
 1.24   0.230  0.305  17459   0.0000 0.0000  Crypt::Blowfish::encrypt
 0.70   0.129  0.818     36   0.0036 0.0227  base::import
 0.59   0.110  0.709     24   0.0046 0.0296  Foo::Bar::FooBarList::BEGIN
 0.44   0.082  0.082   9108   0.0000 0.0000  IO::Wrap::read
 0.40   0.075  0.075  17647   0.0000 0.0000  Crypt::Blowfish::crypt
 0.27   0.050  0.887      7   0.0071 0.1268  main::BEGIN</pre>
<p>统计信息的意思分别是：</p>
<ul class="list1" style="padding-left:16px;margin-left:16px"><li>ExclSec: 函数自身的执行时间（不包括函数调用的其他函数）</li>
<li>CumulS: 函数的执行时间（包括函数调用的其他函数）</li>
<li>#Calls: 调用次数</li>
<li>sec/call: ExceSec/#Calls</li>
<li>Csec/c: CumulS/#Calls</li>
<li>Name: 函数名称</li></ul>
<p>从上面的统计信息中可以看出，Foo::Bar::crypt占用了最多的时间(83.5%)。
而且更为重要的信息是，CumulS - ExclSec = 15.770 - 15.46 = 0.31，
也就是说，绝大部分时间都耗在了 Foo::Bar::crypt 函数本身，而不是它调用的其他函数。
这样，只需针对Foo::Bar::crypt函数进行分析就可以了。</p>
<p>还可以使用另一个性能测试工具<a href="http://tech.idv2.com/2006/10/03/perl-benchmark-by-devel-smallprof/">Devel::SmallProf</a>。</p>
<!-- end Pukiwiki generated code-->

]]></content:encoded>
			<wfw:commentRss>http://tech.idv2.com/2008/10/30/perl-dprof/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[Perl]散列的效率出人意料</title>
		<link>http://tech.idv2.com/2007/12/14/perl-fastest-hash/</link>
		<comments>http://tech.idv2.com/2007/12/14/perl-fastest-hash/#comments</comments>
		<pubDate>Fri, 14 Dec 2007 08:25:14 +0000</pubDate>
		<dc:creator>charlee</dc:creator>
				<category><![CDATA[perl]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[tuning]]></category>

		<guid isPermaLink="false">http://tech.idv2.com/2007/12/14/perl-fastest-hash/</guid>
		<description><![CDATA[<!-- begin Pukiwiki generated code--><p>那天和人讨论一个简单的应用：集合减法，即给定集合 A 和 B ，计算 C = A - B，
也就是说求属于A但不属于B的元素。集合A和B使用数组来存储，元素仅限于整数。
求计算方法。</p>
<p>Perl自身没有集合运算函数，为了这一个功能也犯不上去安装CPAN模块，
所以我们考虑了以下几个方案：</p>
<ol class="list1" style="padding-left:16px;margin-left:16px"><li>利用foreach作最直白的循环来判断</li>
<li>利用grep代替foreach</li>
<li>将元素用逗号连接之后用正则表达式匹配</li>
<li>将数组转化成散列之后判断</li></ol>
<p>四种方法都能实现，但效率如何？本以为使用foreach应该是最快的，
没想到测试之后发现散列居然是最快的。</p>
<pre>              Rate    use grep  use regexp use foreach    use hash
use grep     359/s          --        -58%        -63%        -90%
use regexp   861/s        140%          --        -11%        -77%
use foreach  965/s        169%         12%          --        -74%
use hash    3769/s        950%        338%        291%          --</pre>
<p>如果元素不是整数而是随机的字符串，正则表达式的效率会急剧下降，而散列依然能保证领先的地位。
看来Perl的散列算法不可小觑啊。</p>
<!-- end Pukiwiki generated code--><span id="more-548"></span><!-- begin Pukiwiki generated code--><p>附源代码如下：</p>
<pre>use Benchmark qw(:all);

@a =  (1..100);
@b = (10..200);

sub use_grep {
  my ($a, $b) = @_;
  my @result;
  
  @result = grep {
    my $tmp = $_; 
    !grep{$_ eq $tmp} @$b;
  } @$a;
  
  return \@result;
}
  
sub use_foreach {
  my ($a, $b) = @_;
  my @result;
  
  foreach my $x (@$a){
    my $not_exist = 1;
    foreach my $y (@$b){
      if($x eq $y){
        $not_exist = 0;
        last;
      }
    }
    push @result, $x if ($not_exist);
  }
  
  return \@result;
}

sub use_regexp {
  my ($a, $b) = @_;
  my @result;

  my $str = ',' . (join ',', @$b) . ',';
  foreach (@$a) {
    push @result, $_ unless $str =~ &quot;,$_,&quot;;
  }

  return \@result;
}


sub use_hash {
  my ($a, $b) = @_;
  my @result;
  my %hash;

  foreach (@$b) { $hash{$_} = 1; }
  foreach (@$a) { push @result, $_ unless $hash{$_}; }

  return \@result;
}

#print &quot;use grep: &quot; . (join ',', @{&amp;use_grep(\@a, \@b)}) . &quot;\n&quot;;
#print &quot;use foreach: &quot; . (join ',', @{&amp;use_foreach(\@a, \@b)}) . &quot;\n&quot;;
#print &quot;use regexp: &quot; . (join ',', @{&amp;use_regexp(\@a, \@b)}) . &quot;\n&quot;;
#print &quot;use hash: &quot; . (join ',', @{&amp;use_hash(\@a, \@b)}) . &quot;\n&quot;;

#__END__
cmpthese(3000, {
    'use grep' =&gt; sub { &amp;use_grep(\@a, \@b) },
    'use foreach' =&gt; sub { &amp;use_foreach(\@a, \@b) },
    'use regexp' =&gt; sub { &amp;use_regexp(\@a, \@b) },
    'use hash' =&gt; sub { &amp;use_hash(\@a, \@b) },
});</pre>
<!-- end Pukiwiki generated code-->
]]></description>
			<content:encoded><![CDATA[<!-- begin Pukiwiki generated code--><p>那天和人讨论一个简单的应用：集合减法，即给定集合 A 和 B ，计算 C = A - B，
也就是说求属于A但不属于B的元素。集合A和B使用数组来存储，元素仅限于整数。
求计算方法。</p>
<p>Perl自身没有集合运算函数，为了这一个功能也犯不上去安装CPAN模块，
所以我们考虑了以下几个方案：</p>
<ol class="list1" style="padding-left:16px;margin-left:16px"><li>利用foreach作最直白的循环来判断</li>
<li>利用grep代替foreach</li>
<li>将元素用逗号连接之后用正则表达式匹配</li>
<li>将数组转化成散列之后判断</li></ol>
<p>四种方法都能实现，但效率如何？本以为使用foreach应该是最快的，
没想到测试之后发现散列居然是最快的。</p>
<pre>              Rate    use grep  use regexp use foreach    use hash
use grep     359/s          --        -58%        -63%        -90%
use regexp   861/s        140%          --        -11%        -77%
use foreach  965/s        169%         12%          --        -74%
use hash    3769/s        950%        338%        291%          --</pre>
<p>如果元素不是整数而是随机的字符串，正则表达式的效率会急剧下降，而散列依然能保证领先的地位。
看来Perl的散列算法不可小觑啊。</p>
<!-- end Pukiwiki generated code--><span id="more-548"></span><!-- begin Pukiwiki generated code--><p>附源代码如下：</p>
<pre>use Benchmark qw(:all);

@a =  (1..100);
@b = (10..200);

sub use_grep {
  my ($a, $b) = @_;
  my @result;
  
  @result = grep {
    my $tmp = $_; 
    !grep{$_ eq $tmp} @$b;
  } @$a;
  
  return \@result;
}
  
sub use_foreach {
  my ($a, $b) = @_;
  my @result;
  
  foreach my $x (@$a){
    my $not_exist = 1;
    foreach my $y (@$b){
      if($x eq $y){
        $not_exist = 0;
        last;
      }
    }
    push @result, $x if ($not_exist);
  }
  
  return \@result;
}

sub use_regexp {
  my ($a, $b) = @_;
  my @result;

  my $str = ',' . (join ',', @$b) . ',';
  foreach (@$a) {
    push @result, $_ unless $str =~ &quot;,$_,&quot;;
  }

  return \@result;
}


sub use_hash {
  my ($a, $b) = @_;
  my @result;
  my %hash;

  foreach (@$b) { $hash{$_} = 1; }
  foreach (@$a) { push @result, $_ unless $hash{$_}; }

  return \@result;
}

#print &quot;use grep: &quot; . (join ',', @{&amp;use_grep(\@a, \@b)}) . &quot;\n&quot;;
#print &quot;use foreach: &quot; . (join ',', @{&amp;use_foreach(\@a, \@b)}) . &quot;\n&quot;;
#print &quot;use regexp: &quot; . (join ',', @{&amp;use_regexp(\@a, \@b)}) . &quot;\n&quot;;
#print &quot;use hash: &quot; . (join ',', @{&amp;use_hash(\@a, \@b)}) . &quot;\n&quot;;

#__END__
cmpthese(3000, {
    'use grep' =&gt; sub { &amp;use_grep(\@a, \@b) },
    'use foreach' =&gt; sub { &amp;use_foreach(\@a, \@b) },
    'use regexp' =&gt; sub { &amp;use_regexp(\@a, \@b) },
    'use hash' =&gt; sub { &amp;use_hash(\@a, \@b) },
});</pre>
<!-- end Pukiwiki generated code-->
]]></content:encoded>
			<wfw:commentRss>http://tech.idv2.com/2007/12/14/perl-fastest-hash/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Wordpress性能优化</title>
		<link>http://tech.idv2.com/2007/01/02/wordpress-performance-tuning/</link>
		<comments>http://tech.idv2.com/2007/01/02/wordpress-performance-tuning/#comments</comments>
		<pubDate>Tue, 02 Jan 2007 10:40:57 +0000</pubDate>
		<dc:creator>charlee</dc:creator>
				<category><![CDATA[wordpress]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://tech.inspiremedia.org/archives/317.html</guid>
		<description><![CDATA[<!-- begin Pukiwiki generated code--><p>Wordpress的效率问题似乎一直是议论的热点，今天来看看其中一条SQL语句的效率。</p>
<p>首先将所有插件禁用，并切换为默认模板。
然后按照《<a href="http://www.21andy.com/blog/20060813/374.html">WordPress执行效率问题</a>》这篇文章的方法，
在 wp-config.php 中加入</p>
<pre>&lt;?php define('SAVEQUERIES', true); ?&gt;</pre>
<p>在模板的 footer.php 中加入</p>
<pre>&lt;!-- &lt;?php var_dump($wpdb-&gt;queries); ?&gt; --&gt;</pre>
<p>访问首页，即可从源代码中看到SQL语句。</p>
<p>执行时间最长的是这一条，花了0.02秒：</p>
<pre>SELECT DISTINCT * FROM wp_posts  
WHERE 1=1 
  AND post_date_gmt &lt;= '2007-01-02 07:12:59' 
  AND (
    post_status = 'publish' 
    OR
      post_author = 1 
      AND post_status != 'draft' 
      AND post_status != 'static'
  )
  AND post_status != 'attachment' 
GROUP BY  wp_posts.ID  
ORDER BY post_date DESC 
LIMIT 0, 10&quot;</pre>
<p>这条语句位于 class.php 的 WP_Query-&gt;&amp;get_posts() 函数。</p>
<p>说说这个SQL语句的问题。不妨先来看看 wp_posts 表的结构(省略无关列)。</p>
<div class="ie5"><table class="style_table" cellspacing="1" border="0"><tbody><tr><td class="style_td">列名</td><td class="style_td">类型</td><td class="style_td">索引</td></tr><tr><td class="style_td">ID</td><td class="style_td">bigint(20)</td><td class="style_td">PRIMARY</td></tr><tr><td class="style_td">post_author</td><td class="style_td">bigint(20)</td><td class="style_td"></td></tr><tr><td class="style_td">post_date_gmt</td><td class="style_td">datetime</td><td class="style_td"></td></tr><tr><td class="style_td">post_status</td><td class="style_td">enum</td><td class="style_td">INDEX</td></tr><tr><td class="style_td">post_name</td><td class="style_td">varchar(200)</td><td class="style_td">INDEX</td></tr></tbody></table></div>
<p>首先是关键字 DISTINCT，DISTINCT的作用是去掉重复的数据，
相当于对选择的列进行 GROUP BY。而这条语句中选择了 * 列，包含了主键列 ID，
每行数据必然不相同，因此 DISTINCT 关键字起不到任何作用，
白白浪费一次排序。</p>
<p>其次是 post_date_gmt 和 post_author 上的比较操作。wp_posts表仅有 ID、post_status 和
post_name 列上有索引，对其他列的比较操作使得mysql不得不访问wp_posts表的所有数据，
影响效率。</p>
<p>然后是 post_status 上的不等于的比较。对索引列使用不等于比较，
会导致数据库不能使用索引（索引只能判断等于关系）。
另外显然已经有了 post_status = 'publish' 的条件，
不必再判断 post_status != 'attachment'。</p>
<p>最后是 GROUP BY wp_posts.ID，仍然是对一个不会重复的列进行 GROUP BY，
毫无意义。</p>
<p>如果不考虑功能损失，将这个 SQL 语句优化为下面这样，则仅需花费0.003秒。</p>
<pre>SELECT * FROM wp_posts  
WHERE 1=1 
  AND post_status = 'publish' 
ORDER BY post_date DESC 
LIMIT 0, 10&quot;</pre>
<p>使用Apache Bench做测试，优化前平均每个请求的处理时间为 503.125ms，优化后为 478.125ms。</p>
<!-- end Pukiwiki generated code-->
]]></description>
			<content:encoded><![CDATA[<!-- begin Pukiwiki generated code--><p>Wordpress的效率问题似乎一直是议论的热点，今天来看看其中一条SQL语句的效率。</p>
<p>首先将所有插件禁用，并切换为默认模板。
然后按照《<a href="http://www.21andy.com/blog/20060813/374.html">WordPress执行效率问题</a>》这篇文章的方法，
在 wp-config.php 中加入</p>
<pre>&lt;?php define('SAVEQUERIES', true); ?&gt;</pre>
<p>在模板的 footer.php 中加入</p>
<pre>&lt;!-- &lt;?php var_dump($wpdb-&gt;queries); ?&gt; --&gt;</pre>
<p>访问首页，即可从源代码中看到SQL语句。</p>
<p>执行时间最长的是这一条，花了0.02秒：</p>
<pre>SELECT DISTINCT * FROM wp_posts  
WHERE 1=1 
  AND post_date_gmt &lt;= '2007-01-02 07:12:59' 
  AND (
    post_status = 'publish' 
    OR
      post_author = 1 
      AND post_status != 'draft' 
      AND post_status != 'static'
  )
  AND post_status != 'attachment' 
GROUP BY  wp_posts.ID  
ORDER BY post_date DESC 
LIMIT 0, 10&quot;</pre>
<p>这条语句位于 class.php 的 WP_Query-&gt;&amp;get_posts() 函数。</p>
<p>说说这个SQL语句的问题。不妨先来看看 wp_posts 表的结构(省略无关列)。</p>
<div class="ie5"><table class="style_table" cellspacing="1" border="0"><tbody><tr><td class="style_td">列名</td><td class="style_td">类型</td><td class="style_td">索引</td></tr><tr><td class="style_td">ID</td><td class="style_td">bigint(20)</td><td class="style_td">PRIMARY</td></tr><tr><td class="style_td">post_author</td><td class="style_td">bigint(20)</td><td class="style_td"></td></tr><tr><td class="style_td">post_date_gmt</td><td class="style_td">datetime</td><td class="style_td"></td></tr><tr><td class="style_td">post_status</td><td class="style_td">enum</td><td class="style_td">INDEX</td></tr><tr><td class="style_td">post_name</td><td class="style_td">varchar(200)</td><td class="style_td">INDEX</td></tr></tbody></table></div>
<p>首先是关键字 DISTINCT，DISTINCT的作用是去掉重复的数据，
相当于对选择的列进行 GROUP BY。而这条语句中选择了 * 列，包含了主键列 ID，
每行数据必然不相同，因此 DISTINCT 关键字起不到任何作用，
白白浪费一次排序。</p>
<p>其次是 post_date_gmt 和 post_author 上的比较操作。wp_posts表仅有 ID、post_status 和
post_name 列上有索引，对其他列的比较操作使得mysql不得不访问wp_posts表的所有数据，
影响效率。</p>
<p>然后是 post_status 上的不等于的比较。对索引列使用不等于比较，
会导致数据库不能使用索引（索引只能判断等于关系）。
另外显然已经有了 post_status = 'publish' 的条件，
不必再判断 post_status != 'attachment'。</p>
<p>最后是 GROUP BY wp_posts.ID，仍然是对一个不会重复的列进行 GROUP BY，
毫无意义。</p>
<p>如果不考虑功能损失，将这个 SQL 语句优化为下面这样，则仅需花费0.003秒。</p>
<pre>SELECT * FROM wp_posts  
WHERE 1=1 
  AND post_status = 'publish' 
ORDER BY post_date DESC 
LIMIT 0, 10&quot;</pre>
<p>使用Apache Bench做测试，优化前平均每个请求的处理时间为 503.125ms，优化后为 478.125ms。</p>
<!-- end Pukiwiki generated code-->
]]></content:encoded>
			<wfw:commentRss>http://tech.idv2.com/2007/01/02/wordpress-performance-tuning/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>
