<?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>Erlang非业余研究 &#187; erlc</title>
	<atom:link href="http://blog.yufeng.info/archives/tag/erlc/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.yufeng.info</link>
	<description>Erlang系统深度探索和应用</description>
	<lastBuildDate>Tue, 17 Jan 2012 06:05:54 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Erlang代码反编译以及查看汇编码</title>
		<link>http://blog.yufeng.info/archives/1599</link>
		<comments>http://blog.yufeng.info/archives/1599#comments</comments>
		<pubDate>Sat, 01 Oct 2011 16:46:05 +0000</pubDate>
		<dc:creator>Yu Feng</dc:creator>
				<category><![CDATA[Erlang探索]]></category>
		<category><![CDATA[abstract_code]]></category>
		<category><![CDATA[erlc]]></category>
		<category><![CDATA[erl_syntax]]></category>
		<category><![CDATA[erts_debug]]></category>

		<guid isPermaLink="false">http://blog.yufeng.info/?p=1599</guid>
		<description><![CDATA[原创文章，转载请注明： 转载自Erlang非业余研究 本文链接地址: Erlang代码反编译以及查看汇编码 Erlang的代码是先翻译成abstract_code,再到目标代码的，如果有符号信息很容易恢复源代码，通常我们部署系统的时候需要把符号信息去掉，reltool就可以干这个事情！ 我们演示下： 想查看模块的汇编码，也很容易，这样就好： 了解更多汇编码，请参考这里 祝玩得开心！ Post Footer automatically generated by wp-posturl plugin for wordpress.]]></description>
			<content:encoded><![CDATA[<div style="margin-top: 15px; font-style: italic">
<p><strong>原创文章，转载请注明：</strong> 转载自<a href="http://blog.yufeng.info/">Erlang非业余研究</a></p>
<p><strong>本文链接地址:</strong> <a href="http://blog.yufeng.info/archives/1599">Erlang代码反编译以及查看汇编码</a></p>
</div>
<p>Erlang的代码是先翻译成abstract_code,再到目标代码的，如果有符号信息很容易恢复源代码，通常我们部署系统的时候需要把符号信息去掉，reltool就可以干这个事情！</p>
<p>我们演示下：<br />
<span id="more-1599"></span></p>
<pre class="brush: bash; title: ; notranslate">
$ cat server.erl
-module(server).
-compile(export_all).

start() -&gt;
    start(1234).

start(Port) -&gt;
    register(?MODULE, self()),

    spawn_link(fun ()-&gt; S= listen(Port), accept(S) end),

    receive Any -&gt; io:format(&quot;~p~n&quot;, [Any]) end.  %% to stop: test!stop.

listen(Port) -&gt;
    Opts = [{active, false},
            binary,
            {backlog, 256},
            {packet, raw},
            {reuseaddr, true}],
    {ok, S} = gen_tcp:listen(Port, Opts),
    S.

accept(S) -&gt;
    case gen_tcp:accept(S) of
        {ok, Socket} -&gt; spawn_opt(?MODULE, loop, [Socket,0], []);
        Error    -&gt; erlang:error(Error)
    end,
    accept(S).

loop(S, N) -&gt;
    case gen_tcp:recv(S, 1024) of
        {ok, _Data} -&gt;
	    io:format(&quot;~p got ~w, ~w~n&quot;,[S, size(_Data), N]),
	    timer:sleep(100),
            loop(S, N+1);

        Error -&gt;
            io:format(&quot;tcp ~p~n&quot;, [Error]),
            Error
    end.
$ erlc +debug_info server.erl
$ erl
Erlang R14B04 (erts-5.8.5) 1 [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.8.5  (abort with ^G)
1&gt; f(),{ok, {_, [{abstract_code, {_,Abs}}]}} =  beam_lib:chunks(&quot;server.beam&quot;, [abstract_code]),io:fwrite(&quot;~s~n&quot;, [erl_prettypr:format(erl_syntax:form_list(Abs))]).
-file(&quot;./server.erl&quot;, 1).

-module(server).

-compile(export_all).

start() -&gt; start(1234).

start(Port) -&gt;
    register(server, self()),
    spawn_link(fun () -&gt; S = listen(Port), accept(S) end),
    receive Any -&gt; io:format(&quot;~p~n&quot;, [Any]) end.

listen(Port) -&gt;
    Opts = [{active, false}, binary, {backlog, 256},
            {packet, raw}, {reuseaddr, true}],
    {ok, S} = gen_tcp:listen(Port, Opts),
    S.

accept(S) -&gt;
    case gen_tcp:accept(S) of
      {ok, Socket} -&gt;
          spawn_opt(server, loop, [Socket, 0], []);
      Error -&gt; erlang:error(Error)
    end,
    accept(S).

loop(S, N) -&gt;
    case gen_tcp:recv(S, 1024) of
      {ok, _Data} -&gt;
          io:format(&quot;~p got ~w, ~w~n&quot;, [S, size(_Data), N]),
          timer:sleep(100),
          loop(S, N + 1);
      Error -&gt; io:format(&quot;tcp ~p~n&quot;, [Error]), Error
    end.

ok
2&gt;
</pre>
<p>想查看模块的汇编码，也很容易，这样就好：</p>
<pre class="brush: bash; title: ; notranslate">
$ erl
Erlang R14B04 (erts-5.8.5) 1 [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.8.5  (abort with ^G)
1&gt; erts_debug:df(server).
ok
2&gt; 

$ cat server.dis
0117F108: i_func_info_IaaI 0 server start 0
0117F11C: i_move_call_only_fcr server:start/1 1234 x(0) 

0117F128: i_func_info_IaaI 0 server start 1
0117F13C: allocate_zero_tt 1 1
0117F144: self_x x(1)
0117F14C: move_ry x(0) y(0)
0117F154: move_cr server x(0)
0117F15C: call_bif2_e erlang:register/2
0117F164: move_yr y(0) x(0)
0117F16C: i_make_fun_It 18102836 1
0117F178: init_y y(0)
0117F180: i_call_ext_e erlang:spawn_link/1
0117F188: i_loop_rec_fr f(0117F1B8) x(0)
0117F190: remove_message
0117F194: test_heap_It 2 1
0117F1A0: put_list_rnx x(0) [] x(1)
0117F1A8: i_move_call_ext_last_ePcr io:format/2 1 &quot;~p~n&quot; x(0)
0117F1B8: wait_locked_f f(0117F188) 

0117F1C0: i_func_info_IaaI 0 server listen 1
0117F1D4: allocate_tt 0 1
0117F1DC: move_x1_c [{active,false},binary,{backlog,256},{packet,raw},{reuseaddr,true}]
0117F1E4: i_call_ext_e gen_tcp:listen/2
0117F1EC: is_tuple_of_arity_frA f(0117F218) x(0) 2
0117F1F8: extract_next_element2_x x(1)
0117F200: i_is_eq_exact_immed_fxc f(0117F218) x(1) ok
0117F210: move_deallocate_return_xrQ x(2) x(0) 0
0117F218: badmatch_r x(0) 

0117F21C: i_func_info_IaaI 0 server accept 1
0117F230: allocate_tt 1 1
0117F238: move_ry x(0) y(0)
0117F240: i_call_ext_e gen_tcp:accept/1
0117F248: is_tuple_of_arity_frA f(0117F2AC) x(0) 2
0117F254: extract_next_element2_x x(1)
0117F25C: i_is_eq_exact_immed_fxc f(0117F2AC) x(1) ok
0117F26C: test_heap_It 2 3
0117F278: put_list_xcx x(2) [0] x(2)
0117F284: move_x1_c loop
0117F28C: move_nx [] x(3)
0117F294: i_move_call_ext_cre server x(0) erlang:spawn_opt/4
0117F2A0: move_call_last_yrfQ y(0) x(0) server:accept/1 1
0117F2AC: call_bif1_e erlang:error/1 

0117F2B4: i_func_info_IaaI 0 server loop 2
0117F2C8: allocate_tt 2 2
0117F2D0: move_xy x(1) y(0)
0117F2D8: move_x1_c 1024
0117F2E0: move_ry x(0) y(1)
0117F2E8: i_call_ext_e gen_tcp:recv/2
0117F2F0: is_tuple_of_arity_frA f(0117F388) x(0) 2
0117F2FC: extract_next_element2_x x(1)
0117F304: i_is_eq_exact_immed_fxc f(0117F388) x(1) ok
0117F314: i_gc_bif1_jIsId j(00000000) 151104 x(2) 3 x(0)
0117F32C: test_heap_It 6 3
0117F338: put_list_ynx y(0) [] x(2)
0117F340: put_list_rxr x(0) x(2) x(0)
0117F348: put_list_yrx y(1) x(0) x(1)
0117F350: i_move_call_ext_cre &quot;~p got ~w, ~w~n&quot; x(0) io:format/2
0117F35C: i_move_call_ext_cre 100 x(0) timer:sleep/1
0117F368: i_increment_yIId y(0) 1 0 x(1)
0117F37C: move_call_last_yrfQ y(1) x(0) server:loop/2 2
0117F388: test_heap_It 2 1
0117F394: move_ry x(0) y(1)
0117F39C: put_list_ynx y(1) [] x(1)
0117F3A4: i_trim_I 1
0117F3AC: i_move_call_ext_cre &quot;tcp ~p~n&quot; x(0) io:format/2
0117F3B8: move_deallocate_return_yrQ y(0) x(0) 1 

0117F3C0: i_func_info_IaaI 0 server module_info 0
0117F3D4: move_cr server x(0)
0117F3DC: allocate_tt 0 1
0117F3E4: call_bif1_e erlang:get_module_info/1
0117F3EC: deallocate_return_Q 0 

0117F3F4: i_func_info_IaaI 0 server module_info 1
0117F408: move_rx x(0) x(1)
0117F410: move_cr server x(0)
0117F418: allocate_tt 0 2
0117F420: call_bif2_e erlang:get_module_info/2
0117F428: deallocate_return_Q 0 

0117F430: i_func_info_IaaI 0 server '-start/1-fun-0-' 1
0117F444: allocate_tt 0 1
0117F44C: i_call_f server:listen/1
0117F454: i_call_last_fP server:accept/1 0
</pre>
<p>了解更多汇编码，请参考<a href="http://blog.yufeng.info/archives/tag/erlc">这里</a></p>
<p>祝玩得开心！</p>
<div style="margin-top: 0; margin-bottom: 15px; color: #888888; font-size: 80%; font-style: italic">
<p>Post Footer automatically generated by <a href="http://easwy.com/blog/wordpress/wp-posturl/" style="color: #8888FF; text-decoration: underline;">wp-posturl plugin</a> for wordpress.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.yufeng.info/archives/1599/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Erlang源码汇编格式</title>
		<link>http://blog.yufeng.info/archives/498</link>
		<comments>http://blog.yufeng.info/archives/498#comments</comments>
		<pubDate>Fri, 16 Apr 2010 02:40:40 +0000</pubDate>
		<dc:creator>Yu Feng</dc:creator>
				<category><![CDATA[Erlang探索]]></category>
		<category><![CDATA['s']]></category>
		<category><![CDATA[erlc]]></category>
		<category><![CDATA[erts_dbug:df]]></category>
		<category><![CDATA[opcode]]></category>
		<category><![CDATA[VM]]></category>

		<guid isPermaLink="false">http://blog.yufeng.info/?p=498</guid>
		<description><![CDATA[原创文章，转载请注明： 转载自Erlang非业余研究 本文链接地址: Erlang源码汇编格式 我们在编码的时候, 通常会好奇, 这时候需要观察erl源码生成的VM opcode. Erlang的VM是register based的VM, 生产的opcode很容易理解. 生成汇编格式有2种方式: 1. 从源码生成抽象码. erlc +&#8221;&#8216;S&#8217;&#8221; mod.erl, 生成mod.S 2. 从beam生成Opcode. 未公开的功能. erts_debug:df 参数M或者 M, F, 生成mod.dis 来吧,实践下: 我们得到了eg.S, eg.dis这2个反汇编的结果. 我们再来参观下. 先看源码: root@ubuntu:~/exam# cat eg.erl 中间汇编码, 供transform进行处理和编译器进一步生成opcode. root@ubuntu:~/exam# cat eg.S VM opcode形式, VM就是来解释运行这些code的 收工! Post Footer automatically generated by wp-posturl plugin for wordpress.]]></description>
			<content:encoded><![CDATA[<div style="margin-top: 15px; font-style: italic">
<p><strong>原创文章，转载请注明：</strong> 转载自<a href="http://blog.yufeng.info/">Erlang非业余研究</a></p>
<p><strong>本文链接地址:</strong> <a href="http://blog.yufeng.info/archives/498">Erlang源码汇编格式</a></p>
</div>
<p>我们在编码的时候, 通常会好奇, 这时候需要观察erl源码生成的VM opcode.  Erlang的VM是register based的VM, 生产的opcode很容易理解.<br />
生成汇编格式有2种方式:<br />
1. 从源码生成抽象码. erlc +&#8221;&#8216;S&#8217;&#8221; mod.erl, 生成mod.S<br />
2. 从beam生成Opcode. 未公开的功能. erts_debug:df   参数M或者 M, F, 生成mod.dis</p>
<p>来吧,实践下:</p>
<pre class="brush: bash; title: ; notranslate">
root@ubuntu:~/exam# ls
eg.erl
root@ubuntu:~/exam# erlc +&quot;'S'&quot; eg.erl
root@ubuntu:~/exam# erlc eg.erl
root@ubuntu:~/exam# erl
Erlang R14A (erts-5.8) 1 [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false] [lock-counting]

Eshell V5.8  (abort with ^G)
1&gt;  erts_debug:df(eg).
ok
2&gt;
User switch command
 --&gt; q
root@ubuntu:~/exam# ls eg*
eg.beam  eg.dis  eg.erl  eg.S
</pre>
<p>我们得到了eg.S, eg.dis这2个反汇编的结果. 我们再来参观下.<br />
先看源码:<br />
root@ubuntu:~/exam# cat eg.erl</p>
<pre class="brush: erlang; title: ; notranslate">
-module(eg).
-import(lists).
-import(lists,[sum/1]).
-compile(export_all).

kilo_byte() -&gt;
    kilo_byte(10, [42]).
kilo_byte(0, Acc) -&gt;
    Acc;
kilo_byte(N, Acc) -&gt;
    kilo_byte(N-1, [Acc|Acc]).

loop()-&gt;
    sum(lists:seq(1,100)),
    loop().
</pre>
<p>中间汇编码, 供transform进行处理和编译器进一步生成opcode.<br />
root@ubuntu:~/exam# cat eg.S</p>
<pre class="brush: erlang; title: ; notranslate">
{module, eg}.  %% version = 0

{exports, [{kilo_byte,0},
           {kilo_byte,2},
           {loop,0},
           {module_info,0},
           {module_info,1}]}.

{attributes, []}.

{labels, 12}.

{function, kilo_byte, 0, 2}.
  {label,1}.
    {func_info,{atom,eg},{atom,kilo_byte},0}.
  {label,2}.
    {move,{literal,&quot;*&quot;},{x,1}}.
    {move,{integer,10},{x,0}}.
    {call_only,2,{f,4}}.

{function, kilo_byte, 2, 4}.
  {label,3}.
    {func_info,{atom,eg},{atom,kilo_byte},2}.
  {label,4}.
    {test,is_eq_exact,{f,5},[{x,0},{integer,0}]}.
    {move,{x,1},{x,0}}.
    return.
  {label,5}.
    {gc_bif,'-',{f,0},2,[{x,0},{integer,1}],{x,0}}.
    {test_heap,2,2}.
    {put_list,{x,1},{x,1},{x,1}}.
    {call_only,2,{f,4}}.

{function, loop, 0, 7}.
  {label,6}.
    {func_info,{atom,eg},{atom,loop},0}.
  {label,7}.
    {allocate,0,0}.
    {move,{integer,100},{x,1}}.
    {move,{integer,1},{x,0}}.
    {call_ext,2,{extfunc,lists,seq,2}}.
    {call_ext,1,{extfunc,lists,sum,1}}.
    {call_last,0,{f,7},0}.

{function, module_info, 0, 9}.
  {label,8}.
    {func_info,{atom,eg},{atom,module_info},0}.
  {label,9}.
    {move,{atom,eg},{x,0}}.
    {call_ext_only,1,{extfunc,erlang,get_module_info,1}}.

{function, module_info, 1, 11}.
  {label,10}.
    {func_info,{atom,eg},{atom,module_info},1}.
  {label,11}.
    {move,{x,0},{x,1}}.
    {move,{atom,eg},{x,0}}.
    {call_ext_only,2,{extfunc,erlang,get_module_info,2}}.
</pre>
<p>VM opcode形式, VM就是来解释运行这些code的</p>
<pre class="brush: bash; title: ; notranslate">
root@ubuntu:~/exam# cat eg.dis
B5146074: i_func_info_IaaI 0 eg kilo_byte 0
B5146088: move_cx &quot;*&quot; x(1)
B5146094: i_move_call_only_fcr eg:kilo_byte/2 10 x(0) 

B51460A0: i_func_info_IaaI 0 eg kilo_byte 2
B51460B4: i_is_eq_immed_frc f(B51460C8) x(0) 0
B51460C0: move_return_xr x(1) x(0)
B51460C8: i_fetch_rc x(0) 1
B51460D0: i_minus_jId j(00000000) 2 x(0)
B51460E0: test_heap_II 2 2
B51460EC: put_list_xxx x(1) x(1) x(1)
B51460F4: i_call_only_f eg:kilo_byte/2 

B51460FC: i_func_info_IaaI 0 eg loop 0
B5146110: allocate_tt 0 0
B5146118: move_cx 100 x(1)
B5146124: i_move_call_ext_cre 1 x(0) lists:seq/2
B5146130: i_call_ext_e lists:sum/1
B5146138: i_call_last_fP eg:loop/0 0 

B5146144: i_func_info_IaaI 0 eg module_info 0
B5146158: move_cr eg x(0)
B5146160: allocate_tt 0 1
B5146168: call_bif1_e erlang:get_module_info/1
B5146170: deallocate_return_P 0 

B5146178: i_func_info_IaaI 0 eg module_info 1
B514618C: move_rx x(0) x(1)
B5146194: move_cr eg x(0)
B514619C: allocate_tt 0 2
B51461A4: call_bif2_e erlang:get_module_info/2
B51461AC: deallocate_return_P 0
</pre>
<p>收工!</p>
<div style="margin-top: 0; margin-bottom: 15px; color: #888888; font-size: 80%; font-style: italic">
<p>Post Footer automatically generated by <a href="http://easwy.com/blog/wordpress/wp-posturl/" style="color: #8888FF; text-decoration: underline;">wp-posturl plugin</a> for wordpress.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.yufeng.info/archives/498/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>最快的Erlang http hello world 服务器调优指南 （20Khttp短链接请求/S每桌面CPU)</title>
		<link>http://blog.yufeng.info/archives/105</link>
		<comments>http://blog.yufeng.info/archives/105#comments</comments>
		<pubDate>Tue, 03 Nov 2009 17:20:53 +0000</pubDate>
		<dc:creator>Yu Feng</dc:creator>
				<category><![CDATA[Erlang探索]]></category>
		<category><![CDATA[erlc]]></category>
		<category><![CDATA[hipe]]></category>
		<category><![CDATA[httpd]]></category>
		<category><![CDATA[native]]></category>
		<category><![CDATA[最快]]></category>

		<guid isPermaLink="false">http://blog.yufeng.info/?p=105</guid>
		<description><![CDATA[原创文章，转载请注明： 转载自Erlang非业余研究 本文链接地址: 最快的Erlang http hello world 服务器调优指南 （20Khttp短链接请求/S每桌面CPU) erl的虚拟机有2种方式 plain版本的和smp版本的。 smp版本由于锁的开销相比要比plain版本的慢很多。而32位机器由于内存访问比64位的少，也会快出很多。所有我选择在32位的linux系统下调优这个httpd服务器。这个服务器就是实现个简单的功能，在browser下返回hello world。以下我们会先编译我们的优化版本的虚拟机，然后再分别测试R13B02的标准版本的和我们优化版的性能： 如果编译都没有任何错误的话, 就大功告成了。 好 现在我们开始性能比较： #先加大文件句柄数 #在另外的一台机器上发动ab测试 标准smp版本1个CPU的结果是： 11203.29 [#/sec] (mean) #启用hipe的标准版本 标准smp hipe版本1个CPU结果是： 12390.32 [#/sec] (mean) #我们的优化版本 优化版本单个cpu: 19662.37 [#/sec] (mean) #启用hipe的优化版本 优化版本启用hipe单个cpu:20090.83 [#/sec] (mean) 附上我们的最小的高性能的http echo 服务器： 这个服务器是最小的，单是在多处理器和单cpu上都有非常好的性能。 注：这个http服务器基本上是在c的程序跑，erlang的代码执行的很少， 所以hipe的提升效果不是很明显。对于复杂的业务，应该是有很大的帮助的。 附件里是用到的脚本和补丁。 我们可以得出结论： hipe启用要比不启用快。 优化版本的和标准版本的 20090:11203， 性能提高了将近80% 还是非常可观的。 点击下载附件 Post Footer automatically [...]]]></description>
			<content:encoded><![CDATA[<div style="margin-top: 15px; font-style: italic">
<p><strong>原创文章，转载请注明：</strong> 转载自<a href="http://blog.yufeng.info/">Erlang非业余研究</a></p>
<p><strong>本文链接地址:</strong> <a href="http://blog.yufeng.info/archives/105">最快的Erlang http hello world 服务器调优指南 （20Khttp短链接请求/S每桌面CPU)</a></p>
</div>
<p>erl的虚拟机有2种方式 plain版本的和smp版本的。 smp版本由于锁的开销相比要比plain版本的慢很多。而32位机器由于内存访问比64位的少，也会快出很多。所有我选择在32位的linux系统下调优这个httpd服务器。这个服务器就是实现个简单的功能，在browser下返回hello world。以下我们会先编译我们的优化版本的虚拟机，然后再分别测试R13B02的标准版本的和我们优化版的性能：</p>
<pre class="brush: bash; title: ; notranslate">
root@nd-desktop:/build_opt_plain# uname -a
Linux nd-desktop 2.6.31-14-generic #3 SMP Sun Nov 1 23:03:10 CST 2009 i686 GNU/Linux

#准备开发环境
root@nd-desktop:/# apt-get build-dep erlang

#下载otp R13B02-1源码包
root@nd-desktop:/# wget http://www.erlang.org/download/otp_src_R13B02-1.tar.gz

#解开patch包
root@nd-desktop:/# tar xzvf build_opt_plain.tar.gz

#解开源码包
root@nd-desktop:/# tar xzf otp_src_R13B02-1.tar.gz

#打补丁
root@nd-desktop:/# cd otp_src_R13B02-1
root@nd-desktop:/otp_src_R13B02-1# patch -p1 &lt;../build_opt_plain/otp_src_R13B02-1_patch_by_yufeng
patching file erts/emulator/beam/erl_binary.h
patching file erts/emulator/beam/erl_process.c
patching file erts/emulator/beam/sys.h
patching file erts/emulator/drivers/common/inet_drv.c
patching file erts/preloaded/src/Makefile
patching file erts/preloaded/src/prim_inet.erl
patching file lib/asn1/src/Makefile
patching file lib/hipe/Makefile
patching file lib/parsetools/src/Makefile
root@nd-desktop:/otp_src_R13B02-1# ../build_opt_plain/build.plain
。。。
</pre>
<p>如果编译都没有任何错误的话, 就大功告成了。</p>
<p>好 现在我们开始性能比较：</p>
<p>#先加大文件句柄数</p>
<pre class="brush: bash; title: ; notranslate">
root@nd-desktop:/otp_src_R13B02-1# cd ../build_opt_plain
root@nd-desktop:/build_opt_plain# ulimit -n 99999

#标准发布版本
root@nd-desktop:/build_opt_plain# erlc ehttpd.erl
root@nd-desktop:/build_opt_plain# taskset -c 1 erl +K true +h 99999  +P 99999 -smp enable +S 2:1 -s ehttpd
Erlang R13B03 (erts-5.7.4) 1 [smp:2:1] [rq:2] [async-threads:0] [hipe] [kernel-poll:true]

ehttpd ready with 2 schedulers on port 8888
Eshell V5.7.4  (abort with ^G)
1&gt;
</pre>
<p>#在另外的一台机器上发动ab测试</p>
<pre class="brush: bash; title: ; notranslate">
[root@localhost src]# ab -c 60 -n 100000 http://192.168.235.147:8888/
This is ApacheBench, Version 2.0.40-dev &lt;$Revision: 1.146 $&gt; apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.235.147 (be patient)
Completed 10000 requests
Completed 20000 requests
Completed 30000 requests
Completed 40000 requests
Completed 50000 requests
Completed 60000 requests
Completed 70000 requests
Completed 80000 requests
Completed 90000 requests
Finished 100000 requests

Server Software:
Server Hostname:        192.168.235.147
Server Port:            8888

Document Path:          /
Document Length:        12 bytes

Concurrency Level:      60
Time taken for tests:   8.925945 seconds
Complete requests:      100000
Failed requests:        0
Write errors:           0
Total transferred:      5100051 bytes
HTML transferred:       1200012 bytes
Requests per second:    11203.29 [#/sec] (mean)
Time per request:       5.356 [ms] (mean)
Time per request:       0.089 [ms] (mean, across all concurrent requests)
Transfer rate:          557.92 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    1  65.7      0    3001
Processing:     0    3   1.5      4       7
Waiting:        0    2   1.8      4       6
Total:          0    4  65.8      4    3007
WARNING: The median and mean for the waiting time are not within a normal deviation
        These results are probably not that reliable.

Percentage of the requests served within a certain time (ms)
  50%      4
  66%      4
  75%      4
  80%      4
  90%      5
  95%      5
  98%      5
  99%      5
100%   3007 (longest request)
</pre>
<p>标准smp版本1个CPU的结果是： 11203.29 [#/sec] (mean)</p>
<p>#启用hipe的标准版本</p>
<pre class="brush: bash; title: ; notranslate">
root@nd-desktop:/build_opt_plain# erlc +native +&quot;{hipe, [o3]}&quot; ehttpd.erl
root@nd-desktop:/build_opt_plain# taskset -c 1 erl +K true +h 99999  +P 99999 -smp enable +S 2:1 -s ehttpd
Erlang R13B03 (erts-5.7.4) 1 [smp:2:1] [rq:2] [async-threads:0] [hipe] [kernel-poll:true]

ehttpd ready with 2 schedulers on port 8888
Eshell V5.7.4  (abort with ^G)
1&gt;
</pre>
<p>标准smp hipe版本1个CPU结果是： 12390.32 [#/sec] (mean)</p>
<p>#我们的优化版本</p>
<pre class="brush: bash; title: ; notranslate">
root@nd-desktop:/build_opt_plain#  ../otp_src_R13B02-1/bin/erlc  ehttpd.erl
root@nd-desktop:/build_opt_plain# taskset -c 1   ../otp_src_R13B02-1/bin/erl +K true +h 99999  +P 99999   -s ehttpd
Erlang R13B02 (erts-5.7.3) 1 [rq:1] [hipe] [kernel-poll:true]

ehttpd ready with 1 schedulers on port 8888
Eshell V5.7.3  (abort with ^G)
1&gt;
</pre>
<p>优化版本单个cpu: 19662.37 [#/sec] (mean)</p>
<p>#启用hipe的优化版本</p>
<pre class="brush: bash; title: ; notranslate">
root@nd-desktop:/build_opt_plain#  ../otp_src_R13B02-1/bin/erlc +native +&quot;{hipe, [o3]}&quot;  ehttpd.erl
root@nd-desktop:/build_opt_plain# taskset -c 1   ../otp_src_R13B02-1/bin/erl +K true +h 99999  +P 99999   -s ehttpd
Erlang R13B02 (erts-5.7.3) 1 [rq:1] [hipe] [kernel-poll:true]

ehttpd ready with 1 schedulers on port 8888
Eshell V5.7.3  (abort with ^G)
1&gt;
</pre>
<p>优化版本启用hipe单个cpu:20090.83 [#/sec] (mean)</p>
<p>附上我们的最小的高性能的http echo 服务器：</p>
<pre class="brush: bash; title: ; notranslate">
root@nd-desktop:/build_opt_plain# cat ehttpd.erl
</pre>
<pre class="brush: erlang; title: ; notranslate">
-module(ehttpd).
-compile(export_all).

start() -&gt;
    start(8888).
start(Port) -&gt;
    N = erlang:system_info(schedulers),
    listen(Port, N),
    io:format(&quot;ehttpd ready with ~b schedulers on port ~b~n&quot;, [N, Port]),

    register(?MODULE, self()),
    receive Any -&gt; io:format(&quot;~p~n&quot;, [Any]) end.  %% to stop: ehttpd!stop.

listen(Port, N) -&gt;
    Opts = [{active, false},
            binary,
            {backlog, 256},
            {packet, http_bin},
            {raw,6,9,&lt;&lt;1:32/native&gt;&gt;}, %defer accept
            %%{delay_send,true},
            %%{nodelay,true},
            {reuseaddr, true}],

    {ok, S} = gen_tcp:listen(Port, Opts),
    Spawn = fun(I) -&gt;
                    register(list_to_atom(&quot;acceptor_&quot; ++ integer_to_list(I)),
                             spawn_opt(?MODULE, accept, [S, I], [link, {scheduler, I}]))
            end,
    lists:foreach(Spawn, lists:seq(1, N)).

accept(S, I) -&gt;
    case gen_tcp:accept(S) of
        {ok, Socket} -&gt; spawn_opt(?MODULE, loop, [Socket], [{scheduler, I}]);
        Error    -&gt; erlang:error(Error)
    end,
    accept(S, I).

loop(S) -&gt;
    case gen_tcp:recv(S, 0) of
        {ok, http_eoh} -&gt;
            Response = &lt;&lt;&quot;HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nhello world!&quot;&gt;&gt;,
            gen_tcp:send(S, Response),
            gen_tcp:close(S),
            ok;

        {ok, _Data} -&gt;
            loop(S);

        Error -&gt;
            Error
    end.
</pre>
<p>这个服务器是最小的，单是在多处理器和单cpu上都有非常好的性能。</p>
<pre class="brush: bash; title: ; notranslate">
root@nd-desktop:/build_opt_plain# cat /proc/cpuinfo
model name      : Pentium(R) Dual-Core  CPU      E5200  @ 2.50GHz
</pre>
<p>注：这个http服务器基本上是在c的程序跑，erlang的代码执行的很少， 所以hipe的提升效果不是很明显。对于复杂的业务，应该是有很大的帮助的。</p>
<p>附件里是用到的脚本和补丁。</p>
<p>我们可以得出结论：<br />
hipe启用要比不启用快。<br />
优化版本的和标准版本的 20090:11203， 性能提高了将近80% 还是非常可观的。</p>
<p><a href='http://blog.yufeng.info/wp-content/uploads/2009/11/build_opt_plain.tar.gz'>点击下载附件</a>
<div style="margin-top: 0; margin-bottom: 15px; color: #888888; font-size: 80%; font-style: italic">
<p>Post Footer automatically generated by <a href="http://easwy.com/blog/wordpress/wp-posturl/" style="color: #8888FF; text-decoration: underline;">wp-posturl plugin</a> for wordpress.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.yufeng.info/archives/105/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>实验Erlang语法对应的opcode 让你对erlang理解更深</title>
		<link>http://blog.yufeng.info/archives/34</link>
		<comments>http://blog.yufeng.info/archives/34#comments</comments>
		<pubDate>Sun, 20 Sep 2009 16:59:35 +0000</pubDate>
		<dc:creator>Yu Feng</dc:creator>
				<category><![CDATA[Erlang探索]]></category>
		<category><![CDATA['s']]></category>
		<category><![CDATA[asm]]></category>
		<category><![CDATA[erlc]]></category>

		<guid isPermaLink="false">http://blog.yufeng.info/?p=34</guid>
		<description><![CDATA[原创文章，转载请注明： 转载自Erlang非业余研究 本文链接地址: 实验Erlang语法对应的opcode 让你对erlang理解更深 Erlang作为一门FP语言，和传统的语言结构一样， 有模块， 有函数， 有语句， 有判断， 有循环， 还有特别的模式匹配。 那么这些在底层是如何运作的。 我在底下给大家做个简单的实验，让大家一窥内部的细节，让大家写码的时候知道个大概。 erlang的VM作为register based的VM, 大概有400条指令.指令分为hot, normal, cold 3大类别。beam_emu.c是vm的实现，hot和cold指令在编译的时候 由脚本生成的，include到beam_emu去的。 hot是热门的操作如list, tuple操作, cold的就是比较偏的指令。 erlang的编译器支持生成汇编码， 让我们的研究成可能，具体用法是 erlc +&#8221;&#8216;S&#8217;&#8221; m.erl 会生成m.S 这个汇编文件. 所以无论函数match, 表达式match在vm层面都是if else这样的判断。从这个角度来讲if, case这些都只是erlang的语法糖。事实上也是，这些语法都是后来添加的，取悦用户的。 函数匹配是erlang的所有事情的核心。 结论：erlang的compiler很智能，这个VM和lua的非常像， 效率也相当。 Post Footer automatically generated by wp-posturl plugin for wordpress.]]></description>
			<content:encoded><![CDATA[<div style="margin-top: 15px; font-style: italic">
<p><strong>原创文章，转载请注明：</strong> 转载自<a href="http://blog.yufeng.info/">Erlang非业余研究</a></p>
<p><strong>本文链接地址:</strong> <a href="http://blog.yufeng.info/archives/34">实验Erlang语法对应的opcode 让你对erlang理解更深</a></p>
</div>
<p>Erlang作为一门FP语言，和传统的语言结构一样， 有模块， 有函数， 有语句， 有判断， 有循环， 还有特别的模式匹配。 那么这些在底层是如何运作的。 我在底下给大家做个简单的实验，让大家一窥内部的细节，让大家写码的时候知道个大概。</p>
<p>erlang的VM作为register based的VM, 大概有400条指令.指令分为hot, normal, cold  3大类别。beam_emu.c是vm的实现，hot和cold指令在编译的时候 由脚本生成的，include到beam_emu去的。 hot是热门的操作如list, tuple操作, cold的就是比较偏的指令。</p>
<p>erlang的编译器支持生成汇编码， 让我们的研究成可能，具体用法是 erlc +&#8221;&#8216;S&#8217;&#8221; m.erl<br />
会生成m.S 这个汇编文件.</p>
<pre class="brush: bash; title: ; notranslate">
root@nd-desktop:~# cat gram.erl
</pre>
<pre class="brush: erlang; title: ; notranslate">
-module(gram).
-export([start/1]).

start([X])-&gt;
   %% bif
    X1 = list_to_integer(atom_to_list(X)),

%% list
    W =[1,2,3],
    W1 = [4|W],

    K=[W1,9],

    %% constant fold
    A = 1 + 2,

  %% if
    B =
        if X1 + A &gt; 0 -&gt; 5;
           true -&gt; 4
        end,

   %% case
    C =
    case B of
        {x, T} -&gt; T;
        5 -&gt; a1;
        3 -&gt; a2;
        2 -&gt; 1.0;
        other -&gt; 2;
        true -&gt; 3
    end,

   %% receive
    D =
    receive
        a1 -&gt;
            2 + 1.2;
        2 -&gt; 3;
        {tag, N}-&gt;N;
        a2 -&gt; 5;
        _ -&gt; ok
    after A -&gt;
            timeout
    end,

    %% anon fun
    E = fun (1)-&gt; D;
            (x)-&gt; 2;
            (y)-&gt; C;
            (&lt;&lt;&quot;12&quot;&gt;&gt;)-&gt;1;
            (_) -&gt; error
            end,

    F = E(D),

    %% fun
    G = f(B),

    io:format(&quot;~p~p~p~p~n&quot;,[F, G,W,K]),

    done.

f(1)-&gt; 1;
f(2) -&gt;2;
f(3) -&gt;3;
f(4) -&gt;4;
f(5) -&gt;5;
f(x1) -&gt;1;
f(x2) -&gt;2;
f(x3) -&gt;3;
f(x4) -&gt;4;
f(x5) -&gt;5;
f({x,1}) -&gt; 1;
f({x,2}) -&gt;2;
f({x,3}) -&gt;3;
f({x,4}) -&gt;4;
f({x,5}) -&gt;5;
f(&lt;&lt;1:8, X:32, &quot;xyz&quot;, F/float&gt;&gt;) -&gt; {X, F};
f(_) -&gt; err.
</pre>
<pre class="brush: bash; title: ; notranslate">
root@nd-desktop:~# erlc +&quot;'S'&quot; gram.erl
root@nd-desktop:~# cat gram.S
</pre>
<pre class="brush: erlang; title: ; notranslate">
{module, gram}.  %% version = 0
{exports, [{module_info,0},{module_info,1},{start,1}]}.

{attributes, []}.

{labels, 45}. %%每个标签是跳转地址

%%每个指令对应这相应的opcode,在beam_emu中都可以找到。

{function, start, 1, 2}.
  {label,1}.
    {func_info,{atom,gram},{atom,start},1}.
  {label,2}.
    {test,is_nonempty_list,{f,1},[{x,0}]}.
    {get_list,{x,0},{x,1},{x,2}}.
    {test,is_nil,{f,1},[{x,2}]}.
    {allocate_zero,2,2}.
    {move,{x,1},{x,0}}.
   %% bif调用
    {call_ext,1,{extfunc,erlang,atom_to_list,1}}.
    {call_ext,1,{extfunc,erlang,list_to_integer,1}}.
    %% 符号也是bif
   %% 3= 1 +2 const fold
    {gc_bif,'+',{f,3},1,[{x,0},{integer,3}],{x,1}}.
    %% if 语句是如此简单
    {test,is_lt,{f,3},[{integer,0},{x,1}]}.
    {move,{integer,5},{x,0}}.
    {jump,{f,4}}.
  {label,3}.
    {move,{integer,4},{x,0}}.
  {label,4}.
    {move,{x,0},{y,1}}.
   %% case语句同样是个if else的判断

    %% tuple是如何匹配的 效率高
    {test,is_tuple,{f,5},[{x,0}]}.
    {test,test_arity,{f,21},[{x,0},2]}.
    {get_tuple_element,{x,0},0,{x,1}}.
    {get_tuple_element,{x,0},1,{x,2}}.
    {test,is_eq_exact,{f,21},[{x,1},{atom,x}]}.
    {move,{x,2},{x,0}}.
    {jump,{f,12}}.
  {label,5}.
    {test,is_atom,{f,8},[{x,0}]}.
    %% 2分查找
    {select_val,{x,0},{f,21},{list,[{atom,true},{f,6},{atom,other},{f,7}]}}.
  {label,6}.
    {move,{integer,3},{x,0}}.
    {jump,{f,12}}.
  {label,7}.
    {move,{integer,2},{x,0}}.
    {jump,{f,12}}.
  {label,8}.
    {test,is_integer,{f,21},[{x,0}]}.
   %% 编译器会聪明的做这类事情
    {select_val,{x,0},
                {f,21},
                {list,[{integer,2},
                       {f,9},
                       {integer,3},
                       {f,10},
                       {integer,5},
                       {f,11}]}}.
  {label,9}.
    {move,{float,1.0},{x,0}}.
    {jump,{f,12}}.
  {label,10}.
    {move,{atom,a2},{x,0}}.
    {jump,{f,12}}.
  {label,11}.
    {move,{atom,a1},{x,0}}.
  {label,12}.
    {move,{x,0},{y,0}}.

%% receive语句
  {label,13}.
    {loop_rec,{f,19},{x,0}}.
    {test,is_tuple,{f,14},[{x,0}]}.
    {test,test_arity,{f,18},[{x,0},2]}.
    {get_tuple_element,{x,0},0,{x,1}}.
    {get_tuple_element,{x,0},1,{x,2}}.
    {test,is_eq_exact,{f,18},[{x,1},{atom,tag}]}.

    %%从消息队列移除
    remove_message.
    {move,{x,2},{x,0}}.
    {jump,{f,20}}.
  {label,14}.
    {test,is_atom,{f,17},[{x,0}]}.
    {select_val,{x,0},{f,18},{list,[{atom,a2},{f,15},{atom,a1},{f,16}]}}.
  {label,15}.
    remove_message.
    {move,{integer,5},{x,0}}.
    {jump,{f,20}}.
  {label,16}.
    remove_message.
    {move,{float,3.2},{x,0}}.
    {jump,{f,20}}.
  {label,17}.
    {test,is_eq_exact,{f,18},[{x,0},{integer,2}]}.
    remove_message.
    {move,{integer,3},{x,0}}.
    {jump,{f,20}}.
  {label,18}.
    remove_message.
    {move,{atom,ok},{x,0}}.
    {jump,{f,20}}.
  {label,19}.
    %% timeout添加到定时器
    {wait_timeout,{f,13},{integer,3}}.
    timeout.
    {move,{atom,timeout},{x,0}}.
  {label,20}.
    %% 闭包
    {move,{x,0},{x,1}}.
    {move,{y,0},{x,0}}.
    {move,{x,1},{y,0}}.
    {make_fun2,{f,39},0,133275192,2}.
    {move,{x,0},{x,1}}.
    {move,{y,0},{x,0}}.
    {trim,1,1}.
    {call_fun,1}.
    {move,{x,0},{x,1}}.
    {move,{y,0},{x,0}}.
    {move,{x,1},{y,0}}.
    {call,1,{f,23}}.
    {test_heap,4,1}.
    %% 列表操作
    {put_list,{x,0},{literal,[[1,2,3],[[4,1,2,3],9]]},{x,0}}.
    {put_list,{y,0},{x,0},{x,1}}.
    {trim,1,0}.
    {move,{literal,&quot;~p~p~p~p~n&quot;},{x,0}}.
    {call_ext,2,{extfunc,io,format,2}}.
    {move,{atom,done},{x,0}}.
    {deallocate,0}.
    return.
  {label,21}.
    {case_end,{x,0}}.

{function, f, 1, 23}.
  {label,22}.
    {func_info,{atom,gram},{atom,f},1}.
  {label,23}.
    {test,bs_start_match2,{f,24},1,[{x,0},0],{x,0}}.
    {test,bs_match_string,{f,33},[{x,0},8,{string,[1]}]}.
    {test,bs_get_integer2,
          {f,33},
          1,
          [{x,0},
           {integer,32},
           1,
           {field_flags,[{anno,[78,{file,&quot;./gram.erl&quot;}]},unsigned,big]}],
          {x,1}}.
    {test,bs_match_string,{f,33},[{x,0},24,{string,&quot;xyz&quot;}]}.
    {test,bs_get_float2,
          {f,33},
          2,
          [{x,0},
           {integer,64},
           1,
           {field_flags,[{anno,[78,{file,&quot;./gram.erl&quot;}]},unsigned,big]}],
          {x,2}}.
    {test,bs_test_tail2,{f,33},[{x,0},0]}.
    {test_heap,3,3}.
    {put_tuple,2,{x,0}}.
    {put,{x,1}}.
    {put,{x,2}}.
    return.
  {label,24}.
    {test,is_tuple,{f,25},[{x,0}]}.
    {test,test_arity,{f,33},[{x,0},2]}.
    {get_tuple_element,{x,0},0,{x,1}}.
    {get_tuple_element,{x,0},1,{x,2}}.
    {test,is_eq_exact,{f,33},[{x,1},{atom,x}]}.
    {test,is_integer,{f,33},[{x,2}]}.
    {select_val,{x,2},
                {f,33},
                {list,[{integer,5},
                       {f,26},
                       {integer,4},
                       {f,27},
                       {integer,3},
                       {f,28},
                       {integer,2},
                       {f,29},
                       {integer,1},
                       {f,30}]}}.
  {label,25}.
    {test,is_atom,{f,31},[{x,0}]}.
    {select_val,{x,0},
                {f,33},
                {list,[{atom,x5},
                       {f,26},
                       {atom,x4},
                       {f,27},
                       {atom,x3},
                       {f,28},
                       {atom,x2},
                       {f,29},
                       {atom,x1},
                       {f,30}]}}.
  {label,26}.
    {move,{integer,5},{x,0}}.
    return.
  {label,27}.
    {move,{integer,4},{x,0}}.
    return.
  {label,28}.
    {move,{integer,3},{x,0}}.
    return.
  {label,29}.
    {move,{integer,2},{x,0}}.
    return.
  {label,30}.
    {move,{integer,1},{x,0}}.
    return.
  {label,31}.
    {test,is_integer,{f,33},[{x,0}]}.
    {select_val,{x,0},
                {f,33},
                {list,[{integer,5},
                       {f,32},
                       {integer,4},
                       {f,32},
                       {integer,3},
                       {f,32},
                       {integer,2},
                       {f,32},
                       {integer,1},
                       {f,32}]}}.
  {label,32}.
    return.
  {label,33}.
    {move,{atom,err},{x,0}}.
    return.

%%这2个函数是complier要硬性加上去的

{function, module_info, 0, 35}.
  {label,34}.
    {func_info,{atom,gram},{atom,module_info},0}.
  {label,35}.
    {move,{atom,gram},{x,0}}.
    {call_ext_only,1,{extfunc,erlang,get_module_info,1}}.

{function, module_info, 1, 37}.
  {label,36}.
    {func_info,{atom,gram},{atom,module_info},1}.
  {label,37}.
    {move,{x,0},{x,1}}.
    {move,{atom,gram},{x,0}}.
    {call_ext_only,2,{extfunc,erlang,get_module_info,2}}.

%%匿名函数的命名
{function, '-start/1-fun-0-', 3, 39}.
  {label,38}.
    {func_info,{atom,gram},{atom,'-start/1-fun-0-'},3}.
  {label,39}.
    {test,bs_start_match2,{f,40},3,[{x,0},0],{x,0}}.
    {test,bs_match_string,{f,44},[{x,0},16,{string,&quot;12&quot;}]}.
    {test,bs_test_tail2,{f,44},[{x,0},0]}.
    %% bitstring的代码很优化。
    {move,{integer,1},{x,0}}.
    return.
  {label,40}.
    {test,is_atom,{f,43},[{x,0}]}.
    {select_val,{x,0},{f,44},{list,[{atom,y},{f,41},{atom,x},{f,42}]}}.
   %% 一类的数据放在一起 用二分查找匹配
  {label,41}.
    {move,{x,1},{x,0}}.
    return.
  {label,42}.
    {move,{integer,2},{x,0}}.
    return.
  {label,43}.
    {test,is_eq_exact,{f,44},[{x,0},{integer,1}]}.
    {move,{x,2},{x,0}}.
    return.
  {label,44}.
    {move,{atom,error},{x,0}}.
    return.
</pre>
<p>所以无论函数match, 表达式match在vm层面都是if else这样的判断。从这个角度来讲if, case这些都只是erlang的语法糖。事实上也是，这些语法都是后来添加的，取悦用户的。</p>
<p>函数匹配是erlang的所有事情的核心。</p>
<p>结论：erlang的compiler很智能，这个VM和lua的非常像， 效率也相当。</p>
<div style="margin-top: 0; margin-bottom: 15px; color: #888888; font-size: 80%; font-style: italic">
<p>Post Footer automatically generated by <a href="http://easwy.com/blog/wordpress/wp-posturl/" style="color: #8888FF; text-decoration: underline;">wp-posturl plugin</a> for wordpress.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.yufeng.info/archives/34/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>转：CPU密集型计算 erlang和C 大比拼</title>
		<link>http://blog.yufeng.info/archives/23</link>
		<comments>http://blog.yufeng.info/archives/23#comments</comments>
		<pubDate>Sun, 30 Aug 2009 12:42:28 +0000</pubDate>
		<dc:creator>Yu Feng</dc:creator>
				<category><![CDATA[Erlang探索]]></category>
		<category><![CDATA[erlc]]></category>
		<category><![CDATA[fib]]></category>
		<category><![CDATA[native]]></category>

		<guid isPermaLink="false">http://blog.yufeng.info/?p=23</guid>
		<description><![CDATA[原创文章，转载请注明： 转载自Erlang非业余研究 本文链接地址: 转：CPU密集型计算 erlang和C 大比拼 原文地址：http://pseudelia.wordpress.com/2009/08/23/erlang-native-code-benchmark/ Normalerweise compiliert Erlang Bytecode (heißt das so in Erlang?). Das coole daran ist, dass man die beam files leicht auf anderen Rechnern benutzen kann. Aber die Geschwindigkeit von diesem Code hat mich nicht überzeugen können. Darum habe ich ausprobiert wie gut der native Code ist den Erlang baut. [...]]]></description>
			<content:encoded><![CDATA[<div style="margin-top: 15px; font-style: italic">
<p><strong>原创文章，转载请注明：</strong> 转载自<a href="http://blog.yufeng.info/">Erlang非业余研究</a></p>
<p><strong>本文链接地址:</strong> <a href="http://blog.yufeng.info/archives/23">转：CPU密集型计算 erlang和C 大比拼</a></p>
</div>
<p>原文地址：http://pseudelia.wordpress.com/2009/08/23/erlang-native-code-benchmark/</p>
<p>Normalerweise compiliert <a href="http://www.erlang.org/" target="_blank">Erlang</a> Bytecode (heißt das so in Erlang?). Das coole daran ist, dass man die beam files leicht auf anderen Rechnern benutzen kann. Aber die Geschwindigkeit von diesem Code hat mich nicht überzeugen können. Darum habe ich ausprobiert wie gut der native Code ist den Erlang baut.</p>
<p>Der Versuchsaufbau ist einfach: Ich habe eine simple rekursive Funktion geschrieben, die <a title="Fibonacci-Folge" href="http://de.wikipedia.org/wiki/Fibonacci-Folge" target="_blank">Fibonaccizahlen</a> berechnet. Dann wir 5-mal Fibonacci von 40 berechnet und die Zeit gemessen. Das ganze mache ich mit nur einem Kern. Diesen Test mache ich insgesamt 3-mal. Einmal mit nativem Erlangcode, einmal mit nicht nativem Erlangcode und einmal mit einem in C geschriebenen Programm. Der Benchmark besteht aus drei Dateien:</p>
<p><strong>cpu_intensive.erl:</strong></p>
<pre class="brush: erlang; title: ; notranslate">
-module(cpu_intensive).
-compile(export_all).

fib_test() -&amp;gt;
 fib(40), fib(40), fib(40), fib(40), fib(40).

fib(0) -&amp;gt; 1;
fib(1) -&amp;gt; 1;
fib(N) -&amp;gt; fib(N-1) + fib(N-2).
</pre>
<p><strong>cpu_intensive.c</strong></p>
<pre class="brush: cpp; title: ; notranslate">
unsigned int fib(unsigned int n) {
 if (n == 0 || n == 1) {
 return 1;
 }
 return fib(n-1) + fib(n-2);
}

int main() {
 fib(40); fib(40); fib(40); fib(40); fib(40);
 return 0;
}
</pre>
<p><strong>Makefile:</strong><br />
all: native normal c</p>
<p>native:<br />
 @erlc +native cpu_intensive.erl<br />
 @echo &#8220;&#8221;<br />
 @echo &#8220;Fibonacci Erlang native code&#8221;<br />
 @time erl -noshell -s cpu_intensive fib_test -s erlang halt</p>
<p>normal:<br />
 @erlc cpu_intensive.erl<br />
 @echo &#8220;&#8221;<br />
 @echo &#8220;Fibonacci Erlang non-native code&#8221;<br />
 @time erl -noshell -s cpu_intensive fib_test -s erlang halt</p>
<p>c:<br />
 @gcc -O0 -o cpu_intensive cpu_intensive.c<br />
 @echo &#8220;&#8221;<br />
 @echo &#8220;Fibonacci written in C without optimizations&#8221;<br />
 @time ./cpu_intensive</pre>
<p>Ich habe obige drei Dateien angelegt und die Makefile ausgeführt. Das Ergebnis war bei meinem Core 2 Duo 8400</p>
<p>Fibonacci Erlang native code<br />
 13,99 real        <strong>13,00</strong> user         0,95 sys</p>
<p>Fibonacci Erlang non-native code<br />
 116,81 real       <strong>115,46</strong> user         1,00 sys</p>
<p>Fibonacci written in C without optimizations<br />
 11,14 real        <strong>11,10</strong> user         0,00 sys</p>
<div style="margin-top: 0; margin-bottom: 15px; color: #888888; font-size: 80%; font-style: italic">
<p>Post Footer automatically generated by <a href="http://easwy.com/blog/wordpress/wp-posturl/" style="color: #8888FF; text-decoration: underline;">wp-posturl plugin</a> for wordpress.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.yufeng.info/archives/23/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

