论坛首页 综合技术论坛

erlang编程的小技巧 (持续更新中...)

浏览 6365 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-04-10   最后修改:2010-01-19
这个文章用于记录我遇到的erlang编码中的技巧。

1.
%% http://lukego.livejournal.com/6753.html - that doesn't care about                                                               
%% the order in which results are received.                                                                                        
upmap(F, L) ->
    Parent = self(),
    Ref = make_ref(),
    [receive {Ref, Result} -> Result end
     || _ <- [spawn(fun() -> Parent ! {Ref, F(X)} end) || X <- L]].

2.
http://www.erlang.org/ml-archive/erlang-questions/200301/msg00053.html
Good day,

I've surprisingly found Y-combinator very useful to solve practical
problem of writing recursive anonymous functions in Erlang.

Code were translated to Erlang from
http://www.ece.uc.edu/~franco/C511/html/Scheme/ycomb.html.


-module(lambda).

-export([y/1, mk_fact/0]).

%% Y-combinator itself
y(X) ->
  F = fun (P) -> X(fun (Arg) -> (P(P))(Arg) end) end,
  F(F).

%% Factorial example
mk_fact() ->
  F =
    fun (FA) ->
fun (N) ->
    if (N == 0) -> 1;
       true -> N * FA(N-1)
    end
end
    end,
  y(F).


>From shell:

1> F = mk_fact().
#Fun<lambda.3.115879927>

2> F(5).
120

Best Regards,
Vladimir Sekissov

3.

1> string:concat("hello ", "world").
"hello world"
2> Module = list_to_atom("string").
string
3> Func = list_to_atom("concat").
concat
4> Module:Func("like", "this").
"likethis"


4.
prim模块IO操作与有同步和异步的版本。 但是inet_driver的实现全部是异步的的, 原因是内部使用反应器。


5. vanilla_driver最高效的读文件行的方法
1> erlang:open_port("hello.txt", [stream,line, in,eof]).
#Port<0.480>
2> flush().                                      
Shell got {#Port<0.447>,{data,{eol,"hello"}}}
Shell got {#Port<0.447>,{data,{eol,"world"}}}
Shell got {#Port<0.447>,eof}
ok

6. Break模式下 'o' 查看port消息 未公开

7.
erts_debug:get_internal_state(node_and_dist_references).
/*
  Returns an erlang term on this format:

{{node_references,
   [{{Node, Creation}, Refc,
     [{{ReferrerType, ID},
       [{ReferenceType,References},
'...']},
      '...']},
     '...']},
  {dist_references,
   [{Node, Refc,
     [{{ReferrerType, ID},
       [{ReferenceType,References},
'...']},
      '...']},
    '...']}}
*/

8.
/*
* The "node_tables module" contain two (hash) tables: the node_table
* and the dist_table.
*
* The elements of the node_table represents a specific incarnation of
* an Erlang node and has {Nodename, Creation} pairs as keys. Elements
* in the node_table are referred to from node containers (see
* node_container_utils.h).
*
* The elements of the dist_table represents a (potential) connection
* to an Erlang node and has Nodename as key. Elements in the
* dist_table are either referred to from elements in the node_table
* or from the process or port structure of the entity controlling
* the connection.
*
* Both tables are garbage collected by reference counting.
*/

9.
%%%-----------------------------------------------------------------                                                               
%%% The process structure in kernel is as shown in the figure.                                                                     
%%%                                                                                                                                
%%%               ---------------                                                                                                  
%%%              | kernel_sup (A)|                                                                                                 
%%%               ---------------                                                                                                  
%%%                      |                                                                                                         
%%%        -------------------------------                                                                                         
%%%       |              |                |                                                                                        
%%%  <std services> -------------   -------------                                                                                  
%%%   (file,code,  | erl_dist (A)| | safe_sup (1)|                                                                                 
%%%    rpc, ...)    -------------   -------------                                                                                  
%%%                       |               |                                                                                        
%%%                  (net_kernel,  (disk_log, pg2,                                                                                 
%%%                   auth, ...)     ...)                                                                                          
%%%                                                                                                                                
%%% The rectangular boxes are supervisors.  All supervisors except                                                                 
%%% for kernel_safe_sup terminates the enitre erlang node if any of                                                                
%%% their children dies.  Any child that can't be restarted in case                                                                
%%% of failure must be placed under one of these supervisors.  Any                                                                 
%%% other child must be placed under safe_sup.  These children may                                                                 
%%% be restarted. Be aware that if a child is restarted the old state                                                              
%%% and all data will be lost.  

10。 shell内置命令rp用于看格式化的数据。 比如rp(processes()).

11. OTP-6850: Literal lists, tuples, and binaries are no longer constructed at run-time as they used to be, but are stored in a per-module constant pool. Literals that are used more than once are stored only once.

12. lc可以这样用。
Eshell V5.5.3.1  (abort with ^G)
1> Nums = [1,2,3], Nouns = [shoe,box,tape], Verbs = [].
[]
2> [Nums || Nums =/= []] ++ [Nouns || Nouns =/= []] ++ [Verbs || Verbs
=/= []].
[[1,2,3],[shoe,box,tape]]


13.
node_port(Node)->
    {_, Owner}=lists:keyfind(owner, 1, element(2, net_kernel:node_info(Node))),
    hd([P|| P<-erlang:ports(), erlang:port_info(P, connected) == {connected,Owner}])

14.
inet:setopts(node_port('xx@nd-desktop'), [{high_watermark, 131072}]). 


15.
erl -kernel inet_default_connect_options '[{sndbuf, 1048576}, {high_watermark, 131072}]'

16. ICC 编译选项

export \
CC=icc \
CXX=icpc \
CFLAGS="  -O3 -ip -static   -static-intel -no-gcc -no-prec-div  -mp -unroll2 -xT"  \
CXXFLAGS="-O3 -ip -static -static-intel -no-gcc -no-prec-div  -mp -unroll2 -xT"  \
LDFLAGS='-static -static-intel' \
LD=xild \
AR=xiar 


17.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%                                                                                                                                        
%% Load regulator                                                                                                                                                                                             
%%                                                                                                                                                                                                            
%% This is a poor mans substitute for a fair scheduler algorithm                                                                                                                                              
%% in the Erlang emulator. The mnesia_dumper process performs many                                                                                                                                            
%% costly BIF invokations and must pay for this. But since the                                                                                                                                                
%% Emulator does not handle this properly we must compensate for                                                                                                                                              
%% this with some form of load regulation of ourselves in order to                                                                                                                                            
%% not steal all computation power in the Erlang Emulator ans make                                                                                                                                            
%% other processes starve. Hopefully this is a temporary solution.


18.
The magic commands in the shell. The full list is in the manual, but the ones I use most are:
* f() - forget all variables
* f(X) - forget X
* v(42) - recall result from line 42
* v(-1) - recall result from previous line
* rr(foo) - read record definitions from module foo


19.
beam_lib:chunks can get source code from a beam that was compiled with debug on which can be really usefull
{ok,{_,[{abstract_code,{_,AC}}]}} = beam_lib:chunks(Beam,[abstract_code]).
  io:fwrite("~s~n", [erl_prettypr:format(erl_syntax:form_list(AC))]).

20.
ets:fun2ms(fun({Foo, _, Bar}) when Foo > 0 -> {Foo, Bar} end).
[{{'$1','_','$2'},[{'>','$1',0}],[{{'$1','$2'}}]}]

21.
# erl
Erlang R13B01 (erts-5.7.2) [source] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.7.2  (abort with ^G)
1> H = fun ({trace, _, exit,S},_)-> io:format("got bad arg~p",[S]); (_,_)->skip end.
#Fun<erl_eval.12.113037538>
2> dbg:tracer(process, {H,null}).                                                  
{ok,<0.36.0>}
3> dbg:p(new, [procs]).
{ok,[{matched,nonode@nohost,0}]}
4>
4> spawn(fun() -> abs(x) end).
got bad arg{ok,[{call,2,
                    {atom,2,spawn},
                    [{'fun',2,
                         {clauses,
                             [{clause,2,[],[],
                                  [{call,2,{atom,2,abs},[{atom,2,x}]}]}]}}]}],
               3}got bad arg{badarg,[{erlang,abs,[x]}]}
=ERROR REPORT==== 13-Aug-2009::16:38:56 ===
Error in process <0.40.0> with exit value: {badarg,[{erlang,abs,[x]}]}

<0.40.0>

22;

The condition is specified by the user as a module name CModule and a function name CFunction. When a process reaches the breakpoint, CModule:CFunction(Bindings) will be evaluated. If and only if this function call returns true, the process will stop. If the function call returns false, the breakpoint will be silently ignored.

Bindings is a list of variable bindings. Use the function int:get_binding(Variable,Bindings) to retrieve the value of Variable (given as an atom). The function returns unbound or {value,Value}.

22.

export ERL_TOP=/usr/lib/erlang/

dialyzer --build_plt --output_plt $HOME/.dialyzer_otp.plt -r $ERL_TOP/lib/stdlib/ebin
  $ERL_TOP/lib/kernel/ebin $ERL_TOP/lib/mnesia/ebin $ERL_TOP/lib/ssl/ebin
  $ERL_TOP/lib/asn1/ebin $ERL_TOP/lib/compiler/ebin $ERL_TOP/lib/crypto/ebin
  $ERL_TOP/lib/syntax_tools/ebin $ERL_TOP/lib/inets/ebin $ERL_TOP/lib/sasl/ebin
  $ERL_TOP/lib/odbc/ebin

23. 查看系统的上下文切换
k# cat csw.stp
#!/usr/local/bin/stap -k

global lasttime, times, execnames, switches, csw

probe kernel.function("context_switch") {
#probe scheduler.cpu_off{
  switches ++   # count number of context switches
  now = get_cycles()
  times[pid()] += now-lasttime  # accumulate cycles spent in process
  execnames[pid()] = execname() # remember name of pid
  csw[pid()]++
  lasttime = now
}

probe timer.ms(3000) {

  printf ("\n%10s %30s %20s %20s (%d switches)\n",
          "pid", "execname", "cycles", "csw", switches);

  foreach ([pid] in times-) # sort in decreasing order of cycle-count
    printf ("%10d %30s %20d %20d\n", pid, execnames[pid], times[pid], csw[pid]);

  # clear data for next report
  delete times
  delete execnames
  delete csw

  switches = 0

}

probe begin {
  lasttime = get_cycles()
}

24.
root@nd-desktop:~/test/arksea# cat test.erl
-module(test).

-export([start/0]).

start()->
    {ok, Sock} = gen_tcp:listen(0, []),
    {ok, Handle} = inet:getfd(Sock),
    Command = "erl -noshell -s child -handle " ++ integer_to_list(Handle),
    Child = case (catch open_port({spawn, Command}, [in, {line, 256}])) of
                {'EXIT', Reason}->
                    io:format("open child error, reason ~p~n", [Reason]),
                    halt(1);
                Port-> Port
            end,

    register(?MODULE, self()),
    loop(Child).

loop(Child)->
    receive
        {Child, {data, Result}} ->
            io:format("child say ~p~n", [Result]),
            loop(Child);
        stop->
            halt(0)
    end.

           
root@nd-desktop:~/test/arksea# cat child.erl
-module(child).
-export([start/0]).

start()->
    {ok, [[HandleArg|_]|_]} = init:get_argument(handle),
    Handle = list_to_integer(HandleArg),
    io:format("handle: ~w~n", [Handle]),
    {ok,Socket} = gen_tcp:fdopen(Handle, []),
    io:format("socket: ~p~n", [Socket]),
    halt(0).

25.  Regarding the GC, consider what it has to work with. You are
building a very large data structure in a tight loop. The
process will continuously run out of heap, triggering the GC.
The GC will copy live data (which is going to be most of it)
to another copy of the heap. If that's not enough, it will
run a fullsweep, also looking at data that survived the
previous GC (no garbage there, since the list just keeps
growing). This creates yet another heap copy.
Finally, it does a resize of the heap, if necessary.


26. 反编译
f(),{ok, {_, [{abstract_code, {_,Abs}}]}} =  beam_lib:chunks("xxx.beam", [abstract_code]), io:fwrite("~s~n", [erl_prettypr:format(erl_syntax:form_list(Abs))]).

27.
打印 usage
erl +

   发表时间:2009-04-11  
...
     || _ <- [spawn(fun() -> Parent ! {Ref, F(X)} end) || X <- L]].

是不是 Parent ! {Ref, catch F(X)} 比较稳健泥。。呵呵
0 请登录后投票
   发表时间:2009-04-11  
fail fast,通用的例程不卷入这个判断比较好。
0 请登录后投票
   发表时间:2009-04-11  
忘记这个原则了.
F出错是调用者的事情. 让他自己去管理吧..
0 请登录后投票
   发表时间:2009-08-04  
为什么我使用了第5点的方法,它会循环的读取行,不停的读,而且没有发送{Port, eof}这个标记?  我的版本是R13A,谢谢
0 请登录后投票
   发表时间:2009-08-04  
whrllm 写道
为什么我使用了第5点的方法,它会循环的读取行,不停的读,而且没有发送{Port, eof}这个标记?  我的版本是R13A,谢谢

是不是你的文件很大 你可以试验几行的 这个是c实现的 应该没有问题的。PS 你在那个平台下?linux?

0 请登录后投票
   发表时间:2009-08-04  
文件内容:
boundaryuuid
EF1D2EA88A3ED5D6811230262922518
EF1D2EA88A3ED5D6811230262922519
EF1D2EA88A3ED5D6811230262922520
EF1D2EA88A3ED5D6811230262922521
EF1D2EA88A3ED5D6811230262922522
EF1D2EA88A3ED5D6811230262922523
EF1D2EA88A3ED5D6811230262922524
EF1D2EA88A3ED5D6811230262922525
EF1D2EA88A3ED5D6811230262922526

用的是windows的平台,几乎参数都用过了,都是出现循环读取/没有{Port, eof}这个标志,你可以试试看,R13A
0 请登录后投票
   发表时间:2009-08-04  
结果:
2> erlang:open_port("test1.txt" , [stream , line , in , eof]).
#Port<0.439>
3> flush().
Shell got {#Port<0.439>,{data,{eol,"boundaryuuid "}}}
Shell got {#Port<0.439>,{data,{eol,"EF1D2EA88A3ED5D6811230262922518"}}}
Shell got {#Port<0.439>,{data,{eol,"EF1D2EA88A3ED5D6811230262922519"}}}
……
Shell got {#Port<0.439>,{data,{eol,"boundaryuuid "}}}
Shell got {#Port<0.439>,{data,{eol,"EF1D2EA88A3ED5D6811230262922518"}}}
Shell got {#Port<0.439>,{data,{eol,"EF1D2EA88A3ED5D6811230262922519"}}}
……
Shell got {#Port<0.439>,{data,{eol,"boundaryuuid "}}}
Shell got {#Port<0.439>,{data,{eol,"EF1D2EA88A3ED5D6811230262922518"}}}
Shell got {#Port<0.439>,{data,{eol,"EF1D2EA88A3ED5D6811230262922519"}}}
Shell got {#Port<0.439>,{data,{eol,"EF1D2EA88A3ED5D6811230262922520"}}}
……
0 请登录后投票
   发表时间:2009-08-04  
windows平台估计有问题 在linux下很稳定! 因为otp的小组的开发平台是solaris
0 请登录后投票
论坛首页 综合技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics