I didn't bother with the benchmark part, simply the implementation.
This starts out like mine but the message handling seems a bit more involved. I have to say this exercise is a good one to wrap ones head around functional programming.
-module(ring).
-export([ring/3]).
ring(Proc_count, Msg_count, Msg) ->
First=spawn(fun() -> loop() end), %% first process
links(Proc_count, First, First), %% others
First ! {Proc_count * Msg_count, Msg}. %% send msg to first
links(1, First, Left) ->
First ! {left, Left}; %% tell First who his Left is (last link)
links(Proc, First, Left) ->
P=spawn(fun() -> loop(Left) end),
links(Proc-1, First, P).
loop() -> %% this loop is for First
receive
{left, Left} ->
loop(Left)
end.
loop(Left) ->
receive
{1, Msg} -> %% done
io:format("[~p]: ~p says ~p~n",[1, self(), Msg]);
{Count,Msg} -> %% send message to process on my left
io:format("[~p]: ~p says ~p~n",[Count, self(), Msg]),
Left ! {Count-1, Msg },
loop(Left)
end.