Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:24
erlang
6216-stdlib-Optimize-fun-usage.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 6216-stdlib-Optimize-fun-usage.patch of Package erlang
From 3346acf491bf33267242f9100bd32da92f090d44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20H=C3=B6gberg?= <john@erlang.org> Date: Tue, 19 Oct 2021 20:18:51 +0200 Subject: [PATCH 6/6] stdlib: Optimize fun usage Hoisting the fun check outside these loops lets us skip error checks on the fun calls themselves, which is very nice for functions like foldl/3. --- lib/debugger/test/fun_SUITE.erl | 2 +- lib/kernel/test/code_SUITE.erl | 19 +++- lib/stdlib/src/gb_sets.erl | 2 +- lib/stdlib/src/lists.erl | 195 ++++++++++++++++++++++---------- lib/stdlib/src/sets.erl | 16 ++- 5 files changed, 162 insertions(+), 72 deletions(-) diff --git a/lib/debugger/test/fun_SUITE.erl b/lib/debugger/test/fun_SUITE.erl index 7eb53e4ce4..962c54f22a 100644 --- a/lib/debugger/test/fun_SUITE.erl +++ b/lib/debugger/test/fun_SUITE.erl @@ -289,7 +289,7 @@ eep37(Config) when is_list(Config) -> 10 = Add(9), 50 = UnusedName(8), [1,1,2,6,24,120] = lists:map(F, lists:seq(0, 5)), - {'EXIT',{{badarity,_},_}} = (catch lists:map(fun G() -> G() end, [1])), + {'EXIT',{function_clause,_}} = (catch lists:map(fun G() -> G() end, [1])), {'EXIT',{{badarity,_},_}} = (catch F()), ok. diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index 740f05ac94..5227346217 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -869,13 +869,15 @@ check_funs({'$M_EXPR','$F_EXPR',_}, [{code_server,do_mod_call,4}, {code_server,handle_call,3}|_]) -> 0; check_funs({'$M_EXPR','$F_EXPR',_}, - [{lists,flatmap,2}, + [{lists,flatmap_1,2}, + {lists,flatmap,2}, {lists,concat,1}, {code_server,load_abs,4}, {code_server,handle_call,3}, {code_server,loop,1}|_]) -> 0; check_funs({'$M_EXPR','$F_EXPR',_}, - [{lists,foreach,2}, + [{lists,foreach_1,2}, + {lists,foreach,2}, {code_server,stick_dir,3}, {code_server,handle_call,3}, {code_server,loop,1}|_]) -> 0; @@ -891,6 +893,19 @@ check_funs({'$M_EXPR','$F_EXPR',1}, {code_server,get_user_lib_dirs,0}, {code_server,init,3}, {code_server,start_link,1}]) -> 0; +check_funs({'$M_EXPR','$F_EXPR',1}, + [{lists,all_1,2}, + {lists,all,2}, + {code_server,is_numstr,1}, + {code_server,is_vsn,1}, + {code_server,vsn_to_num,1}, + {code_server,create_bundle,2}, + {code_server,choose_bundles,1}, + {code_server,make_path,2}, + {code_server,get_user_lib_dirs_1,1}, + {code_server,get_user_lib_dirs,0}, + {code_server,init,3}, + {code_server,start_link,1}]) -> 0; check_funs({'$M_EXPR','$F_EXPR',1}, [{lists,filter,2}, {code_server,try_archive_subdirs,3}|_]) -> 0; diff --git a/lib/stdlib/src/gb_sets.erl b/lib/stdlib/src/gb_sets.erl index 6d6f7d40ac..8dda0d4ee0 100644 --- a/lib/stdlib/src/gb_sets.erl +++ b/lib/stdlib/src/gb_sets.erl @@ -871,7 +871,7 @@ is_set(_) -> false. Set1 :: set(Element), Set2 :: set(Element). -filter(F, S) -> +filter(F, S) when is_function(F, 1) -> from_ordset([X || X <- to_list(S), F(X)]). -spec fold(Function, Acc0, Set) -> Acc1 when diff --git a/lib/stdlib/src/lists.erl b/lib/stdlib/src/lists.erl index b82732e0ca..63d55f5630 100644 --- a/lib/stdlib/src/lists.erl +++ b/lib/stdlib/src/lists.erl @@ -1231,24 +1231,46 @@ rumerge(T1, [H2 | T2]) -> List :: [T], T :: term(). -all(Pred, [Hd|Tail]) -> +all(Pred, List) when is_function(Pred, 1) -> + case List of + [Hd | Tail] -> + case Pred(Hd) of + true -> all_1(Pred, Tail); + false -> false + end; + [] -> true + end. + +all_1(Pred, [Hd | Tail]) -> case Pred(Hd) of - true -> all(Pred, Tail); - false -> false + true -> all_1(Pred, Tail); + false -> false end; -all(Pred, []) when is_function(Pred, 1) -> true. +all_1(_Pred, []) -> + true. -spec any(Pred, List) -> boolean() when Pred :: fun((Elem :: T) -> boolean()), List :: [T], T :: term(). -any(Pred, [Hd|Tail]) -> +any(Pred, List) when is_function(Pred, 1) -> + case List of + [Hd | Tail] -> + case Pred(Hd) of + true -> true; + false -> any_1(Pred, Tail) + end; + [] -> false + end. + +any_1(Pred, [Hd | Tail]) -> case Pred(Hd) of - true -> true; - false -> any(Pred, Tail) + true -> true; + false -> any_1(Pred, Tail) end; -any(Pred, []) when is_function(Pred, 1) -> false. +any_1(_Pred, []) -> + false. -spec map(Fun, List1) -> List2 when Fun :: fun((A) -> B), @@ -1257,9 +1279,16 @@ any(Pred, []) when is_function(Pred, 1) -> false. A :: term(), B :: term(). -map(F, [H|T]) -> - [F(H)|map(F, T)]; -map(F, []) when is_function(F, 1) -> []. +map(F, List) when is_function(F, 1) -> + case List of + [Hd | Tail] -> [F(Hd) | map_1(F, Tail)]; + [] -> [] + end. + +map_1(F, [Hd | Tail]) -> + [F(Hd) | map_1(F, Tail)]; +map_1(_F, []) -> + []. -spec flatmap(Fun, List1) -> List2 when Fun :: fun((A) -> [B]), @@ -1268,9 +1297,13 @@ map(F, []) when is_function(F, 1) -> []. A :: term(), B :: term(). -flatmap(F, [Hd|Tail]) -> - F(Hd) ++ flatmap(F, Tail); -flatmap(F, []) when is_function(F, 1) -> []. +flatmap(F, List) when is_function(F, 1) -> + flatmap_1(F, List). + +flatmap_1(F, [Hd | Tail]) -> + F(Hd) ++ flatmap_1(F, Tail); +flatmap_1(_F, []) -> + []. -spec foldl(Fun, Acc0, List) -> Acc1 when Fun :: fun((Elem :: T, AccIn) -> AccOut), @@ -1281,9 +1314,16 @@ flatmap(F, []) when is_function(F, 1) -> []. List :: [T], T :: term(). -foldl(F, Accu, [Hd|Tail]) -> - foldl(F, F(Hd, Accu), Tail); -foldl(F, Accu, []) when is_function(F, 2) -> Accu. +foldl(F, Accu, List) when is_function(F, 2) -> + case List of + [Hd | Tail] -> foldl_1(F, F(Hd, Accu), Tail); + [] -> Accu + end. + +foldl_1(F, Accu, [Hd | Tail]) -> + foldl_1(F, F(Hd, Accu), Tail); +foldl_1(_F, Accu, []) -> + Accu. -spec foldr(Fun, Acc0, List) -> Acc1 when Fun :: fun((Elem :: T, AccIn) -> AccOut), @@ -1294,9 +1334,13 @@ foldl(F, Accu, []) when is_function(F, 2) -> Accu. List :: [T], T :: term(). -foldr(F, Accu, [Hd|Tail]) -> - F(Hd, foldr(F, Accu, Tail)); -foldr(F, Accu, []) when is_function(F, 2) -> Accu. +foldr(F, Accu, List) when is_function(F, 2) -> + foldr_1(F, Accu, List). + +foldr_1(F, Accu, [Hd | Tail]) -> + F(Hd, foldr_1(F, Accu, Tail)); +foldr_1(_F, Accu, []) -> + Accu. -spec filter(Pred, List1) -> List2 when Pred :: fun((Elem :: T) -> boolean()), @@ -1317,15 +1361,15 @@ filter(Pred, List) when is_function(Pred, 1) -> NotSatisfying :: [T], T :: term(). -partition(Pred, L) -> - partition(Pred, L, [], []). +partition(Pred, L) when is_function(Pred, 1) -> + partition_1(Pred, L, [], []). -partition(Pred, [H | T], As, Bs) -> +partition_1(Pred, [H | T], As, Bs) -> case Pred(H) of - true -> partition(Pred, T, [H | As], Bs); - false -> partition(Pred, T, As, [H | Bs]) + true -> partition_1(Pred, T, [H | As], Bs); + false -> partition_1(Pred, T, As, [H | Bs]) end; -partition(Pred, [], As, Bs) when is_function(Pred, 1) -> +partition_1(_Pred, [], As, Bs) -> {reverse(As), reverse(Bs)}. -spec filtermap(Fun, List1) -> List2 when @@ -1335,16 +1379,20 @@ partition(Pred, [], As, Bs) when is_function(Pred, 1) -> Elem :: term(), Value :: term(). -filtermap(F, [Hd|Tail]) -> +filtermap(F, List) when is_function(F, 1) -> + filtermap_1(F, List). + +filtermap_1(F, [Hd|Tail]) -> case F(Hd) of - true -> - [Hd|filtermap(F, Tail)]; - {true,Val} -> - [Val|filtermap(F, Tail)]; - false -> - filtermap(F, Tail) + true -> + [Hd | filtermap_1(F, Tail)]; + {true,Val} -> + [Val | filtermap_1(F, Tail)]; + false -> + filtermap_1(F, Tail) end; -filtermap(F, []) when is_function(F, 1) -> []. +filtermap_1(_F, []) -> + []. -spec zf(fun((T) -> boolean() | {'true', X}), [T]) -> [(T | X)]. @@ -1356,10 +1404,14 @@ zf(F, L) -> List :: [T], T :: term(). -foreach(F, [Hd|Tail]) -> +foreach(F, List) when is_function(F, 1) -> + foreach_1(F, List). + +foreach_1(F, [Hd | Tail]) -> F(Hd), - foreach(F, Tail); -foreach(F, []) when is_function(F, 1) -> ok. + foreach_1(F, Tail); +foreach_1(_F, []) -> + ok. -spec mapfoldl(Fun, Acc0, List1) -> {List2, Acc1} when Fun :: fun((A, AccIn) -> {B, AccOut}), @@ -1372,11 +1424,15 @@ foreach(F, []) when is_function(F, 1) -> ok. A :: term(), B :: term(). -mapfoldl(F, Accu0, [Hd|Tail]) -> - {R,Accu1} = F(Hd, Accu0), - {Rs,Accu2} = mapfoldl(F, Accu1, Tail), - {[R|Rs],Accu2}; -mapfoldl(F, Accu, []) when is_function(F, 2) -> {[],Accu}. +mapfoldl(F, Accu, List) when is_function(F, 2) -> + mapfoldl_1(F, Accu, List). + +mapfoldl_1(F, Accu0, [Hd | Tail]) -> + {R, Accu1} = F(Hd, Accu0), + {Rs, Accu2} = mapfoldl_1(F, Accu1, Tail), + {[R | Rs], Accu2}; +mapfoldl_1(_F, Accu, []) -> + {[], Accu}. -spec mapfoldr(Fun, Acc0, List1) -> {List2, Acc1} when Fun :: fun((A, AccIn) -> {B, AccOut}), @@ -1389,11 +1445,15 @@ mapfoldl(F, Accu, []) when is_function(F, 2) -> {[],Accu}. A :: term(), B :: term(). -mapfoldr(F, Accu0, [Hd|Tail]) -> - {Rs,Accu1} = mapfoldr(F, Accu0, Tail), - {R,Accu2} = F(Hd, Accu1), - {[R|Rs],Accu2}; -mapfoldr(F, Accu, []) when is_function(F, 2) -> {[],Accu}. +mapfoldr(F, Accu, List) when is_function(F, 2) -> + mapfoldr_1(F, Accu, List). + +mapfoldr_1(F, Accu0, [Hd|Tail]) -> + {Rs, Accu1} = mapfoldr_1(F, Accu0, Tail), + {R, Accu2} = F(Hd, Accu1), + {[R | Rs], Accu2}; +mapfoldr_1(_F, Accu, []) -> + {[], Accu}. -spec takewhile(Pred, List1) -> List2 when Pred :: fun((Elem :: T) -> boolean()), @@ -1401,12 +1461,16 @@ mapfoldr(F, Accu, []) when is_function(F, 2) -> {[],Accu}. List2 :: [T], T :: term(). -takewhile(Pred, [Hd|Tail]) -> +takewhile(Pred, List) when is_function(Pred, 1) -> + takewhile_1(Pred, List). + +takewhile_1(Pred, [Hd | Tail]) -> case Pred(Hd) of - true -> [Hd|takewhile(Pred, Tail)]; - false -> [] + true -> [Hd | takewhile_1(Pred, Tail)]; + false -> [] end; -takewhile(Pred, []) when is_function(Pred, 1) -> []. +takewhile_1(_Pred, []) -> + []. -spec dropwhile(Pred, List1) -> List2 when Pred :: fun((Elem :: T) -> boolean()), @@ -1414,24 +1478,31 @@ takewhile(Pred, []) when is_function(Pred, 1) -> []. List2 :: [T], T :: term(). -dropwhile(Pred, [Hd|Tail]=Rest) -> +dropwhile(Pred, List) when is_function(Pred, 1) -> + dropwhile_1(Pred, List). + +dropwhile_1(Pred, [Hd | Tail]=Rest) -> case Pred(Hd) of - true -> dropwhile(Pred, Tail); - false -> Rest + true -> dropwhile_1(Pred, Tail); + false -> Rest end; -dropwhile(Pred, []) when is_function(Pred, 1) -> []. +dropwhile_1(_Pred, []) -> + []. -spec search(Pred, List) -> {value, Value} | false when Pred :: fun((T) -> boolean()), List :: [T], Value :: T. -search(Pred, [Hd|Tail]) -> +search(Pred, List) when is_function(Pred, 1) -> + search_1(Pred, List). + +search_1(Pred, [Hd | Tail]) -> case Pred(Hd) of true -> {value, Hd}; - false -> search(Pred, Tail) + false -> search_1(Pred, Tail) end; -search(Pred, []) when is_function(Pred, 1) -> +search_1(_Pred, []) -> false. -spec splitwith(Pred, List) -> {List1, List2} when @@ -1442,14 +1513,14 @@ search(Pred, []) when is_function(Pred, 1) -> T :: term(). splitwith(Pred, List) when is_function(Pred, 1) -> - splitwith(Pred, List, []). + splitwith_1(Pred, List, []). -splitwith(Pred, [Hd|Tail], Taken) -> +splitwith_1(Pred, [Hd|Tail], Taken) -> case Pred(Hd) of - true -> splitwith(Pred, Tail, [Hd|Taken]); + true -> splitwith_1(Pred, Tail, [Hd|Taken]); false -> {reverse(Taken), [Hd|Tail]} end; -splitwith(Pred, [], Taken) when is_function(Pred, 1) -> +splitwith_1(_Pred, [], Taken) -> {reverse(Taken),[]}. -spec split(N, List1) -> {List2, List3} when diff --git a/lib/stdlib/src/sets.erl b/lib/stdlib/src/sets.erl index 086de0f202..e272b33bf6 100644 --- a/lib/stdlib/src/sets.erl +++ b/lib/stdlib/src/sets.erl @@ -426,8 +426,10 @@ is_subset_1(Set, Iter) -> Acc1 :: Acc, AccIn :: Acc, AccOut :: Acc. -fold(F, Acc, #{}=D) -> fold_1(F, Acc, maps:iterator(D)); -fold(F, Acc, #set{}=D) -> fold_set(F, Acc, D). +fold(F, Acc, #{}=D) when is_function(F, 2)-> + fold_1(F, Acc, maps:iterator(D)); +fold(F, Acc, #set{}=D) when is_function(F, 2)-> + fold_set(F, Acc, D). fold_1(Fun, Acc, Iter) -> case maps:next(Iter) of @@ -443,8 +445,10 @@ fold_1(Fun, Acc, Iter) -> Pred :: fun((Element) -> boolean()), Set1 :: set(Element), Set2 :: set(Element). -filter(F, #{}=D) -> maps:from_keys(filter_1(F, maps:iterator(D)), ?VALUE); -filter(F, #set{}=D) -> filter_set(F, D). +filter(F, #{}=D) when is_function(F, 1)-> + maps:from_keys(filter_1(F, maps:iterator(D)), ?VALUE); +filter(F, #set{}=D) when is_function(F, 1)-> + filter_set(F, D). filter_1(Fun, Iter) -> case maps:next(Iter) of @@ -482,7 +486,7 @@ get_bucket(T, Slot) -> get_bucket_s(T#set.segs, Slot). %% implemented map and hash using fold but these should be faster. %% We hope! -fold_set(F, Acc, D) when is_function(F, 2) -> +fold_set(F, Acc, D) -> Segs = D#set.segs, fold_segs(F, Acc, Segs, tuple_size(Segs)). @@ -499,7 +503,7 @@ fold_bucket(F, Acc, [E|Bkt]) -> fold_bucket(F, F(E, Acc), Bkt); fold_bucket(_, Acc, []) -> Acc. -filter_set(F, D) when is_function(F, 1) -> +filter_set(F, D) -> Segs0 = tuple_to_list(D#set.segs), {Segs1,Fc} = filter_seg_list(F, Segs0, [], 0), maybe_contract(D#set{segs = list_to_tuple(Segs1)}, Fc). -- 2.31.1
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor