Archive

Posts Tagged ‘beam_receive’

R14A添加新指令优化Ref消息的接收

May 19th, 2010 1 comment

原创文章,转载请注明: 转载自系统技术非业余研究

本文链接地址: R14A添加新指令优化Ref消息的接收

Erlang的惯用法之一就是在消息匹配的时候,如果需要唯一性,通常会通过make_ref搞个唯一的Ref来作为消息的一部分来匹配。这个惯用法用在gen_server:call或者demonitor这样的使用频度很高的函数里面。由于erlang的消息匹配是再消息队列里面挨个遍历来匹配,特别是消息队列特别长的时候,会有很大的性能瓶颈。于是新的优化出现了,以下是编译器beam_receive.erl里面的解释,写的很清楚:

%%%                                                                                                                                                                    
%%% In code such as:                                                                                                                                                   
%%%                                                                                                                                                                    
%%%    Ref = make_ref(),        %Or erlang:monitor(process, Pid)                                                                                                       
%%%      .                                                                                                                                                             
%%%      .                                                                                                                                                             
%%%      .                                                                                                                                                             
%%%    receive                                                                                                                                                         
%%%       {Ref,Reply} -> Reply                                                                                                                                         
%%%    end.                                                                                                                                                            
%%%                                                                                                                                                                    
%%% we know that none of the messages that exist in the message queue                                                                                                  
%%% before the call to make_ref/0 can be matched out in the receive                                                                                                    
%%% statement. Therefore we can avoid going through the entire message                                                                                                 
%%% queue if we introduce two new instructions (here written as                                                                                                        
%%% BIFs in pseudo-Erlang):                                                                                                                                            
%%%                                                                                                                                                                    
%%%    recv_mark(SomeUniqInteger),                                                                                                                                     
%%%    Ref = make_ref(),                                                                                                                                               
%%%      .                                                                                                                                                             
%%%      .                                                                                                                                                             
%%%      .                                                                                                                                                             
%%%    recv_set(SomeUniqInteger),                                                                                                                                      
%%%    receive                                                                                                                                                         
%%%       {Ref,Reply} -> Reply                                                                                                                                         
%%%    end.                                                                                                                                                            
%%%                                                                                                                                                                    
%%% The recv_mark/1 instruction will save the current position and                                                                                                     
%%% SomeUniqInteger in the process context. The recv_set                                                                                                               
%%% instruction will verify that SomeUniqInteger is still stored                                                                                                       
%%% in the process context. If it is, it will set the current pointer                                                                                                  
%%% for the message queue (the next message to be read out) to the                                                                                                     
%%% position that was saved by recv_mark/1.                                                                                                                            
%%%    
%%% The remove_message instruction must be modified toinvalidate                                                                                                      
%%% the information stored by the previous recv_mark/1, in case there                                                                                                  
%%% is another receive executed between the calls to recv_mark/1 and                                                                                                   
%%% recv_set/1.                                                                                                                                                        
%%%                                                                                                                                                                    
%%% We use a reference to a label (i.e. a position in the loaded code)                                                                                                 
%%% as the SomeUniqInteger.                                                                                                                                            
%%%                                                   

结论: 点滴优化成就高性能。

Post Footer automatically generated by wp-posturl plugin for wordpress.