Skip to content

Instantly share code, notes, and snippets.

@bjorng
Created April 25, 2017 10:36
Show Gist options
  • Save bjorng/f21ed529fff0a8134f378723e6fbcd78 to your computer and use it in GitHub Desktop.
Save bjorng/f21ed529fff0a8134f378723e6fbcd78 to your computer and use it in GitHub Desktop.
Compare two directories of .S files, producing a summary of the change of function sizes
#!/usr/bin/env escript
%% -*- erlang -*-
-mode(compile).
-import(lists, [foreach/2]).
main([Old,New]) ->
Wc = filename:join(Old, "*.S"),
Files0 = filelib:wildcard(Wc),
Files = [filename:basename(F) || F <- Files0],
F = fun(Name) ->
diff(Old, New, Name)
end,
Data = lists:sort(p_run(F, Files)),
print_summary(Data).
print_summary(Data) ->
io:nl(),
foreach(fun ({_Name,0,1.0,_Funcs}) ->
ok;
({Name,Diff,P,Funcs}) ->
io:format("~35s | ~8w | ~.2f%~n", [Name,Diff,P*100.0]),
foreach(fun ({{F,A},D,Pf}) ->
io:format("~35s : ~8w | ~w/~w (~.2f%)~n",
["",D,F,A,Pf*100.0])
end, Funcs)
end, Data).
diff(Old, New, Name) ->
{SzOld,FOld} = prepare(Old, Name),
{SzNew,FNew} = prepare(New, Name),
J = sofs:to_external(sofs:join(FOld, 1, FNew, 1)),
Funcs = [{FA,N2-N1,N2/N1} || {FA,N1,N2} <- J, N1 =/= N2],
{ok,{Name,SzNew-SzOld,SzNew/SzOld,Funcs}}.
prepare(Dir, Name) ->
File = filename:join(Dir, Name),
{ok,Ts} = file:consult(File),
Sz = length(Ts),
{Sz,sofs:relation(group(Ts))}.
group(Is) ->
group_functions(Is, header, 0).
group_functions([{function,Fun,Arity,_}|Is], FA, Out) ->
[{FA,Out}|group_functions(Is, {Fun,Arity}, 0)];
group_functions([_|Is], FA, Out) ->
group_functions(Is, FA, Out+1);
group_functions([], FA, Out) ->
[{FA,Out}].
%%%
%%% Run tasks in parallel.
%%%
p_run(Task, List) ->
N = erlang:system_info(schedulers) * 2,
p_run_loop(Task, List, N, [], [], 0).
p_run_loop(_, [], _, [], Result, Errors) ->
io:put_chars("\r \n"),
case Errors of
0 ->
Result;
N ->
io:format("~p errors\n", [N]),
halt(1)
end;
p_run_loop(Task, [H|T], N, Refs, Result, Errors) when length(Refs) < N ->
{_,Ref} = erlang:spawn_monitor(fun() -> exit(Task(H)) end),
p_run_loop(Task, T, N, [Ref|Refs], Result, Errors);
p_run_loop(Task, List, N, Refs0, Result0, Errors0) ->
io:format("\r~p ", [length(List)+length(Refs0)]),
receive
{'DOWN',Ref,process,_,Exit} ->
{Result,Errors} = case Exit of
{ok,Res} ->
{[Res|Result0],Errors0};
error ->
{Result0,Errors0 + 1}
end,
Refs = Refs0 -- [Ref],
p_run_loop(Task, List, N, Refs, Result, Errors)
end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment