[erlang PR猎人] Optimize v3_kernel for thousands of clauses #2165

栏目: Erlang · 发布时间: 6年前

内容简介:本 PR 中, Jose Valim 优化了以下这一段逻辑被删除了, 这里对 Cs 有一次遍历:它首先对 Cs 中所有的 clause 做了

本 PR 中, Jose Valim 优化了 v3_kernel 中对于 match clauses 的处理函数 match_con/4 , 在有上千个clauses 的情况下, 编译速度有 10% 的提升.

以下这一段逻辑被删除了, 这里对 Cs 有一次遍历:

%% old
match_con(Us, Cs0, Def, St) ->
    %% Expand literals at the top level.
    Cs = [expand_pat_lit_clause(C) || C <- Cs0],
    match_con_1(Us, Cs, Def, St).
复制代码

它首先对 Cs 中所有的 clause 做了 expand_pat_lit_clause/1 操作. 之后 match_con_1/4 函数体中的逻辑, 与新代码中有些许不同:

%% old
match_con_1([U|_Us] = L, Cs, Def, St0) ->
    %% Extract clauses for different constructors (types).
    %%ok = io:format("match_con ~p~n", [Cs]),
    Ttcs0 = select_types([k_binary], Cs) ++ select_bin_con(Cs) ++
        select_types([k_cons,k_tuple,k_map,k_atom,k_float,
                      k_int,k_nil], Cs),
    Ttcs = opt_single_valued(Ttcs0),

%% new
match_con([U|_Us] = L, Cs, Def, St0) ->
    Ttcs0 = select_types(Cs, [], [], [], [], [], [], [], [], []),
    Ttcs1 = [{T, Types} || {T, [_ | _] = Types} <- Ttcs0],
    Ttcs = opt_single_valued(Ttcs1),
复制代码

注意到, 在执行最后一行之前, 都通过 select_types 函数对 Cs 做了处理. 在old 代码中, 对于 k_binary type, 要遍历一次Cs; 对于 select_bin_con , 又要遍历一次 Cs; 对于其它 types, 还要遍历一次 Cs. 而在new 代码中, 只遍历了一次 Cs. select_types 函数是这个 PR 里改动最大的地方, 让我们来看一下:

%% old
select_types(Types, Cs) ->
    [{T,Tcs} || T <- Types, begin Tcs = select(T, Cs), Tcs =/= [] end].

%% select(Con, [Clause]) -> [Clause].

select(T, Cs) -> [ C || C <- Cs, clause_con(C) =:= T ].


%% new
select_types([NoExpC | Cs], Bin, BinCon, Cons, Tuple, Map, Atom, Float, Int, Nil) ->
    C = expand_pat_lit_clause(NoExpC),
    case clause_con(C) of
	k_binary ->
	    select_types(Cs, [C |Bin], BinCon, Cons, Tuple, Map, Atom, Float, Int, Nil);
	k_bin_seg ->
	    select_types(Cs, Bin, [C | BinCon], Cons, Tuple, Map, Atom, Float, Int, Nil);
	k_bin_end ->
	    select_types(Cs, Bin, [C | BinCon], Cons, Tuple, Map, Atom, Float, Int, Nil);
	k_cons ->
	    select_types(Cs, Bin, BinCon, [C | Cons], Tuple, Map, Atom, Float, Int, Nil);
	k_tuple ->
	    select_types(Cs, Bin, BinCon, Cons, [C | Tuple], Map, Atom, Float, Int, Nil);
	k_map ->
	    select_types(Cs, Bin, BinCon, Cons, Tuple, [C | Map], Atom, Float, Int, Nil);
	k_atom ->
	    select_types(Cs, Bin, BinCon, Cons, Tuple, Map, [C | Atom], Float, Int, Nil);
	k_float ->
	    select_types(Cs, Bin, BinCon, Cons, Tuple, Map, Atom, [C | Float], Int, Nil);
	k_int ->
	    select_types(Cs, Bin, BinCon, Cons, Tuple, Map, Atom, Float, [C | Int], Nil);
	k_nil ->
	    select_types(Cs, Bin, BinCon, Cons, Tuple, Map, Atom, Float, Int, [C | Nil])
    end;
select_types([], Bin, BinCon, Cons, Tuple, Map, Atom, Float, Int, Nil) ->
    [{k_binary, reverse(Bin)}] ++ handle_bin_con(reverse(BinCon)) ++
	[
	    {k_cons, reverse(Cons)},
	    {k_tuple, reverse(Tuple)},
	    {k_map, reverse(Map)},
	    {k_atom, reverse(Atom)},
	    {k_float, reverse(Float)},
	    {k_int, reverse(Int)},
	    {k_nil, reverse(Nil)}
	].
复制代码

注意到尽管新代码里只需要遍历一次 Cs, 但最后的结果还是要每个小 list 都做一次反转的. 所以, 此 PR 的性能优化点是在把对于一个 list 的四次遍历变为了一次遍历, 在 list 很长的情况下优化会更明显.


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

从0到1

从0到1

彼得·蒂尔、布莱克·马斯特斯 / 高玉芳 / 中信出版股份有限公司 / 2015-1-1 / CNY 45.00

图书简介: http://v.youku.com/v_show/id_XOTA0NjcyMzE2.html?wm=3333_2001 硅谷创投教父、PayPal创始人作品,斯坦福大学改变未来的一堂课,为世界创造价值的商业哲学。 在科技剧烈改变世界的今天,想要成功,你必须在一切发生之前研究结局。 你必须找到创新的独特方式,让未来不仅仅与众不同,而且更加美好。 从0到1,......一起来看看 《从0到1》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具