tags:

views:

382

answers:

4

The following is a erlang function. I don't understand how lists:map function is used here. Could someone please explain?

% perform M runs with N calls to F in each run.
% For each of the M runs, determine the average time per call.
% Return, the average and standard deviation of these M results.

time_it(F, N, M) ->
      G = fun() -> F(), ok end,
      NN = lists:seq(1, N),
      MM = lists:seq(1, M),
      T = lists:map(
            fun(_) ->
          T0 = now(),    % start timer
          [ G() || _ <- NN ],    % make N calls to F
          1.0e-6*timer:now_diff(now(), T0)/N % average time per call
        end,
        MM
          ),
      { avg(T), std(T) }.

Thanks.

also, I don't know the proper syntax when using this function. For example, I have a dummy() function take 1 parameter. I get an error while trying to time the dummy function.

moduleName:time_it(moduleName:dummy/1, 10, 100).

the above would evaluate to illegal expression.

Actually, now with the correct syntax, the function can be invoked correctly with:

moduleName:time_it(fun moduleName:dummy/1, 10, 100).

However, it will throw a exception saying invoking dummy function without passing any parameter. I think this line is the villain, [ G() || _ <- NN ], I have no idea how to fix it.

+3  A: 

map is used here to execute the function

T0 = now(),                           % start timer
[ G() || _ <- NN ],                   % make N calls to F
1.0e-6*timer:now_diff(now(), T0)/N    % average time per call

for each element of MM. map will return a new list of the same size, where each element of the new list is the result of applying the above function to the corresponding element of MM.

You can invoke time_it like:

moduleName:time_it(fun moduleName:dummy/1, 10, 100).
sepp2k
A: 
results(N, F) when N >= 0 -> results(N, F, []).
results(0, _, Acc) -> lists:reverse(Acc);
results(N, F, Acc) -> results(N-1, F, [F() | Acc]).

repeat(0, F) -> ok;
repeat(N, F) when N > 0 ->
    F(),
    repeat(N-1, F).

With these:

T = results(M, fun () ->
                   T0 = now(),
                   repeat(N, G),
                   1.0e-6 * timer:now_diff(now(), T0)/N
               end)

Make sense, now?

ayrnieu
+1  A: 

If you have a function moduleName:dummy/1 you can do one of the following

  1. If you can edit time_it/3, then make it call F(constant_parameter) instead of F(). I assume this is the case.
  2. Otherwise, call M1:time_it(fun() -> M2:dummy(constant_parameter) end, N, M). dummy will not be called directly, but only by F inside time_it.
+1  A: 

The purpose of lists:map in the time_it function is just to run the inner function M times. When you see this pattern:

L = lists:seq(1,M),
lists:map(fun(_)-> Foo() end, L)

It just means call Foo() again and again M times, and return the results of each call in a list. It actually makes a list of integers [1,2,3,...N] and then calls Foo() once for each member of the list. The author of time_it does this same trick again, because time_it needs to call the function you give it N*M times. So inside the outer loop that runs M times they use a different technique to run the inner loop N times:

L = lists:seq(1,N),
[Foo() || _ <- L]

This has exactly the same result as the code above, but this time Foo is called N times.

The reason you are having trouble using time_it with your dummy function is that time_it takes a function with 0 parameters, not 1. So you need to make a dummy function and call it like this:

dummy() -> 
    %% do something here you want to measure
    ok.

measure_dummy() ->
    time_it(fun someModule:dummy/0, 10, 100).
Rob Charlton