Permalink
Browse files

Optimize Separate when there are many sub-objects

wings_util:array_smallest_key/1 gets increasingly slower as the
number of 'undefined' entries before the first defined entry
in the array increases. It is a big win to keep track of the
next possible position where we can find a defined entry.

We can also save some time in separate/3 if we avoid putting edges
that we have already copied into the working set.
  • Loading branch information...
1 parent e44eafd commit 729380bfeb02e6c23d62becc3e02c0968176ff16 @bjorng bjorng committed Oct 3, 2009
Showing with 19 additions and 15 deletions.
  1. +19 −15 src/wings_we.erl
View
@@ -787,35 +787,39 @@ update_id_bounds(#we{vp=Vtab,es=Etab,fs=Ftab}=We) ->
separate(We0) ->
We = break_mirror(We0),
- separate(We#we{vc=undefined,fs=undefined}, []).
+ separate_1(We#we{vc=undefined,fs=undefined}, 0, []).
-separate(#we{es=Etab0}=We, Acc) ->
+separate_1(#we{es=Etab0}=We, Smallest0, Acc) ->
case wings_util:array_is_empty(Etab0) of
true -> Acc;
false ->
- Edge = wings_util:array_smallest_key(Etab0),
+ {Edge,Smallest} = smallest(Smallest0, Etab0),
Ws = gb_sets:singleton(Edge),
{EtabLeft,NewEtab} = separate(Ws, Etab0, array:new()),
NewWe = copy_dependents(We#we{es=NewEtab}),
- separate(We#we{es=EtabLeft}, [NewWe|Acc])
+ separate_1(We#we{es=EtabLeft}, Smallest, [NewWe|Acc])
end.
separate(Ws0, Etab0, Acc0) ->
case gb_sets:is_empty(Ws0) of
true -> {Etab0,Acc0};
false ->
{Edge,Ws1} = gb_sets:take_smallest(Ws0),
- case array:get(Edge, Etab0) of
- undefined ->
- separate(Ws1, Etab0, Acc0);
- Rec ->
- Etab = array:reset(Edge, Etab0),
- Acc = array:set(Edge, Rec, Acc0),
- #edge{ltpr=LP,ltsu=LS,rtpr=RP,rtsu=RS} = Rec,
- Set = gb_sets:from_list([LP,LS,RP,RS]),
- Ws = gb_sets:union(Ws1, Set),
- separate(Ws, Etab, Acc)
- end
+ Rec = array:get(Edge, Etab0),
+ Etab = array:reset(Edge, Etab0),
+ Acc = array:set(Edge, Rec, Acc0),
+ #edge{ltpr=LP,ltsu=LS,rtpr=RP,rtsu=RS} = Rec,
+ List = [E || E <- [LP,LS,RP,RS],
+ array:get(E, Etab) =/= undefined],
+ Set = gb_sets:from_list(List),
+ Ws = gb_sets:union(Ws1, Set),
+ separate(Ws, Etab, Acc)
+ end.
+
+smallest(I, A) ->
+ case array:get(I, A) of
+ undefined -> smallest(I+1, A);
+ _ -> {I,I+1}
end.
copy_dependents(We0) ->

0 comments on commit 729380b

Please sign in to comment.