Help needed

Joe Armstrong joe@REDACTED
Tue Apr 30 15:43:22 CEST 2002

Further to my previous mails I need to know which functions in the
standard system are used by your applications.

I want to find out if we can simplify the system by removing all the crud 
that is never used.

I have included an analyse program - this program computes the set of
all MFA's in the standard system  which are called by a given set of

I would be grateful if you you run this program on your applications
and send me the results - I need these results to help me figure out how 
the system can be simplified. 

To run this program edit the module (the instructions are in the 
file) then run it "anal2:run()" and then post me the resultant file

Once you send me your anlysis I can take the grand union of all these 
files and compute the set of things that got called.

The set of things that are exported - the set of things that are called
is the *interesting* thing.

Note: I am particularly keen that users with large applications send me 
their results.


-------------- next part --------------

-export([test/0, run/0]).

%% To run this program
%%   1) edit the function my_apps() with your applications
%%   2) run anal2:run()
%%   3) post the resulting file to

-import(lists, [foldl/3, foreach/2, map/2, sum/1, member/2, sort/1]).

%% Edit the next line with your applications

my_apps() -> [x1, x2, x4].

%% edit this with your Identifier

id() -> "My project identifier". %% like AXD301 :-)

%%   test() -- test the system
%%   run()  -- the full run

test() -> go(libs(cos), libs(big)).

run() ->  go(my_apps(), libs(all)).

libs(small) ->
    [stdlib, kernel, sasl];
libs(big) ->
libs(cos) ->
libs(all) ->
    libs(big) ++ libs(cos).

go(MyApps, SysLibs) ->
    {ok, P} = xref:start(a),
    M1 = add_libs(P, SysLibs),
    io:format("~nStandard libraries have ~w modules~n", [length(M1)]),
    M2 = add_libs(P, MyApps),
    io:format("~nApplication libraries have ~w modules~n", [length(M2)]),
    D = used_calls(P, M2, M1, dict:new()),
    D1 = dict:to_list(D),
    D2 = lists:sort(fun({_,N},{_,M}) -> N > M end, D1),
    {ok, S} = file:open("call_analysis.txt", write),
    io:format(S, "~p.~n", [{id(), D2}]),
    Sum = sum(map(fun({_,N}) -> N end, D1)),
    io:format("Standard system functions are called ~w times~n", [Sum]),
    io:format("call_analysis.txt created -- please send to joe@REDACTED~n"),

used_calls(P, [Mod|T], M1, Dict) ->
    E = Mod:module_info(exports),
    E1 = remove_locals(E),
    %% io:format("Here E1=: ~p~n", [E1]),
    Dict2 = foldl(fun({Func,Arity}, Dict1) ->
			  case xref:analyse(P, {call,{Mod,Func,Arity}}) of
			      {ok, L1} ->
				  update_dict(L1, M1, Dict1);
				  io:format("oops:~p ~p~n", 
					    [{Mod,Func,Arity}, X]),
		  end, Dict, E1),
    used_calls(P, T, M1, Dict2);
used_calls(P, [], M1, Dict) ->

update_dict([Key={M,F,A}|T], Sys, Dict) ->
    case member(M, Sys) of
	true ->
	    case dict:find(Key, Dict) of
		error ->
		    D1 = dict:store(Key, 1, Dict),
		    update_dict(T, Sys, D1);
		{ok, N } ->
		    D1 = dict:store(Key, N+1, Dict),
		    update_dict(T, Sys, D1)
	false ->
	    update_dict(T, Sys, Dict)
update_dict([], _, D) ->

add_libs(P, L) ->
    foldl(fun(I, A) ->
		  Dir = code:lib_dir(I) ++ "/ebin",
		  io:format(".", []),
		  case xref:add_directory(P, Dir, [{warnings,false}]) of
		      {ok, X} ->
			  X ++ A;
		      _ ->
	  end, [], L).

remove_locals([{module_info,_}|T]) -> remove_locals(T);
remove_locals([H|T])               -> [H|remove_locals(T)];
remove_locals([])                  -> [].

More information about the erlang-questions mailing list