1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
  
     | 
    
      %% -*- erlang-indent-level: 2 -*-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Copyright (c) 2001 by Erik Johansson.  All Rights Reserved 
%% Time-stamp: <2008-04-20 14:53:36 richard>
%% ====================================================================
%%  Filename : 	hipe_timer.erl
%%  Module   :	hipe_timer
%%  Purpose  :  
%%  Notes    : 
%%  History  :	* 2001-03-15 Erik Johansson (happi@it.uu.se): 
%%               Created.
%%  CVS      :
%%              $Author: richardc $
%%              $Date: 2008/04/20 13:01:14 $
%%              $Revision: 1.4 $
%% ====================================================================
%%  Exports  :
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-module(hipe_timer).
-export([tr/1,t/1,timer/1,time/1,empty_time/0]).
-export([advanced/2]).
t(F) ->
  {EWT,ERT} = empty_time(),
  {WT,RT} = time(F),
  {WT-EWT,(RT-ERT)/1000}.
tr(F) ->
  {EWT,ERT} = empty_time(),
  {R,{WT,RT}} = timer(F),
  {R,{WT-EWT,(RT-ERT)/1000}}.
  
empty_time() ->
  {WT1,WT2,WT3}=erlang:now(),
  {A,_}=erlang:statistics(runtime),
  {WT12,WT22,WT32}=erlang:now(),
  {B,_}=erlang:statistics(runtime),
  {(WT12-WT1)*1000000+(WT22-WT2)+(WT32-WT3)/1000000,B-A}.
time(F) -> 
  {WT1,WT2,WT3}=erlang:now(),
  {A,_}=erlang:statistics(runtime),
  F(),
  {WT12,WT22,WT32}=erlang:now(),
  {B,_}=erlang:statistics(runtime),
  {(WT12-WT1)*1000000+(WT22-WT2)+(WT32-WT3)/1000000,B-A}.
timer(F) -> 
  {WT1,WT2,WT3}=erlang:now(),
  {A,_}=erlang:statistics(runtime),
  R = F(),
  {WT12,WT22,WT32}=erlang:now(),
  {B,_}=erlang:statistics(runtime),
  {R,{(WT12-WT1)*1000000+(WT22-WT2)+(WT32-WT3)/1000000,B-A}}.
advanced(_Fun, I) when I < 2 -> false;
advanced(Fun, Iterations) ->
  S = lists:seq(1,Iterations),
  R = Fun(),
  Measurements = 
    lists:map(fun (_) ->
		  t(Fun)
	      end, S),
  {Wallclock, RunTime} = split(Measurements),
  WMin = min(Wallclock),
  RMin = min(RunTime),
  WMax = max(Wallclock),
  RMax = max(RunTime),
  WMean = mean(Wallclock),
  RMean = mean(RunTime),
  WMedian = median(Wallclock),
  RMedian = median(RunTime),
  WVariance = variance(Wallclock),
  RVariance = variance(RunTime),
  WStddev = stddev(Wallclock),
  RStddev = stddev(RunTime),
  WVarCoff = 100 * WStddev / WMean,
  RVarCoff = 100 * RStddev / RMean,
  WSum = lists:sum(Wallclock),
  RSum = lists:sum(RunTime),
  [{wallclock,[{min,WMin},
	       {max,WMax},
	       {mean,WMean},
	       {median,WMedian},
	       {variance,WVariance},
	       {stdev,WStddev},
	       {varcoff, WVarCoff},
	       {sum, WSum},
	       {values,Wallclock}	       
	       ]},
  {runtime,[{min,RMin},
	       {max,RMax},
	       {mean,RMean},
	       {median,RMedian},
	       {variance,RVariance},
	       {stdev,RStddev},
	       {varcoff, RVarCoff},
	       {sum, RSum},
	       {values,RunTime}	       
	       ]},
   {iterations, Iterations},
   {result,R}
   ].
min([V|Vs]) ->
  min(Vs,V).
min([V|Vs], Min) when V >= Min ->
  min(Vs,Min);
min([V|Vs], _) ->
  min(Vs, V);
min([],Min) -> Min.
max([V|Vs]) ->
  max(Vs,V).
max([V|Vs], Max) when V =< Max ->
  max(Vs,Max);
max([V|Vs], _) ->
  max(Vs, V);
max([],Max) -> Max.
  
split(M) -> 
  split(M,[],[]).
split([{W,R}|More], AccW, AccR) ->
  split(More, [W|AccW], [R|AccR]);
split([],AccW, AccR) ->
  {AccW, AccR}.
  
mean(L) ->
  mean(L,0,0).
mean([V|Vs], No, Sum) ->
  mean(Vs,No+1,Sum+V);
mean([], No, Sum) when No > 0 ->
  Sum/No;
mean([], _No, _Sum) ->
  exit(empty_list).
  
median(L) ->
  S = length(L),
  SL = lists:sort(L),
  case even(S) of
    true ->
      (lists:nth((S div 2),SL) +
       lists:nth((S div 2)+1,SL)) / 2;
    false ->
       lists:nth((S div 2),SL)
  end.
even(S) ->
  (S band 1) =:= 0.
%% diffs(L,V) ->
%%   lists:map(fun(X) ->
%%		X - V
%%	    end, L).
square_diffs(L,V) ->
  lists:map(fun(X) ->
		D = (X - V),
		D * D
	    end, L).
variance(L) ->
  Mean = mean(L),
  N = length(L),
  if N > 1 ->
      lists:sum(square_diffs(L,Mean)) / (N-1);
     true -> exit(two_few_values)
  end.
stddev(L) ->
  math:sqrt(variance(L)).
 
     |