[erlang-questions] dialyzer orelse filter slowness

Tobias Lindahl tobias.lindahl@REDACTED
Thu Mar 26 09:53:04 CET 2009



Nick Conrad wrote:
> Hello,
> 
> I've got a module that dialyzer takes more than 15 minutes to analyze,  
> and I've narrowed down the cause to a fairly long orelse expression  
> that is being used as a filter in a list comprehension.  If I replace  
> the orelse expression with a function call and make each individual  
> test it's own function, dialyzer is much happier and completes within  
> seconds.  Does anyone have an explanation for why dialyzer might take  
> so long on the orelse's when used as a filter?

orelse is expanded by the compiler to a case expression, so basically 
your long line of orelses becomes deeply nested cases.

Dialyzer analyses each function (or rather each strongly connected 
component of functions) in isolation, and abstracts the types at the 
function borders, so when you break your tests into different functions 
it is just a matter of analyzing a bunch of very simple functions which 
explains why Dialyzer is fast there.

In contrast, the function with the deeply nested case is analyzed 
without abstraction, and the relatively complicated control structure 
makes the analysis pretty slow.

I hope that this will be faster in R13 because of an improvement in the 
compilation of orelses.

Tobias

> 
> Here's a bit of code that demonstrates the issue, which I've seen  
> using both R11B and R12B.
> 
> --
> -module (test).
> -export ([ foo/1 ]).
> 
> -ifdef (USE_ORELSE).
> -define (bar (F),
>          ((F) =:= a orelse
>           (F) =:= b orelse
>           (F) =:= c orelse
>           (F) =:= d orelse
>           (F) =:= e orelse
>           (F) =:= f orelse
>           (F) =:= g orelse
>           (F) =:= h orelse
>           (F) =:= i orelse
>           (F) =:= j orelse
>           (F) =:= k)).
> -else.
> -define (bar, bar_f).
>           bar_f (a) -> true;
>           bar_f (b) -> true;
>           bar_f (c) -> true;
>           bar_f (d) -> true;
>           bar_f (e) -> true;
>           bar_f (f) -> true;
>           bar_f (g) -> true;
>           bar_f (h) -> true;
>           bar_f (i) -> true;
>           bar_f (j) -> true;
>           bar_f (k) -> true;
>           bar_f (_) -> false.
> -endif.
> 
> foo (List) ->
>   [ F || F <- List, ?bar (F)].
> --
> 
> 
> % dialyzer --no_check_plt --src -c .
>   Proceeding with analysis... done in 0m0.23s
> done (passed successfully)
> 
> % dialyzer -DUSE_ORELSE=1 --no_check_plt --src -c .
>   Proceeding with analysis... done in 0m32.24s
> done (passed successfully)
> 
> Thanks!
> - n
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://www.erlang.org/mailman/listinfo/erlang-questions



More information about the erlang-questions mailing list