Fastest pseudo-random number-generator: erlang:statistics(io) ?

Thijs <>
Wed Nov 25 02:33:00 CET 2009


On Nov 25, 2:59 am, Jayson Vantuyl <> wrote:
> Is it too slow to run the result through erlang:phash/2?

I tested it, erlang:phash2(erlang:statistics(io), 10) it still is
fast, but significantly slower than without. You are right that it
immediately scales the result, so i tested with scaling the
erlang:statistics(io) as well. I think the randomness (for my case)
will not improve a lot, but I will keep this function in mind.


On Nov 25, 12:10 am, "Zoltan Lajos Kis" <> wrote:
> How about process_info(self(), reductions). ?
This one is also very fast (only a bit slower than statistics(io)),
but I am concerned about the randomness of this function (at least in
my case). I have many short-lived processes and it's likely that the
number of reductions for each process might be quite similar if they
follow similar code paths?

new benchmark results:

          erlang_now req/sec   296667.7
            stats_io req/sec  2638898.4
    stats_wall_clock req/sec   289306.0
       stats_runtime req/sec   522258.4
    stats_reductions req/sec   484499.9
   stats_cont_switch req/sec   491190.3
      random_uniform req/sec  1109517.1
  process_info_reduc req/sec  2410724.8
           phash2_io req/sec  1773493.0
     stats_io_scaled req/sec  2357073.0


tested like this:

---------------------------

test_random_speed(ParCount, SeqCount) ->
	FunErlangNow =  fun() -> erlang:now() end,
	FunIO =  fun() -> erlang:statistics(io) end,
	FunWallClock =  fun() -> erlang:statistics(wall_clock) end,
	FunRuntime =  fun() -> erlang:statistics(runtime) end,
	FunReductions =  fun() -> erlang:statistics(reductions) end,
	FunContextSwitches =  fun() -> erlang:statistics(context_switches)
end,
	FunRandomUniform =  fun() -> random:uniform() end,
	FunProcessInfoRed = fun() -> erlang:process_info(self(), reductions)
end,
	FunPhashIO  = fun() -> erlang:phash2(erlang:statistics(io), 10) end,
	FunIOScaled =  fun() ->
							{{input, Input}, {output, Output}} = erlang:statistics(io),
							(Input+Output) rem 10
						end,

	test_fun_x_times_parallel(erlang_now, FunErlangNow, ParCount,
SeqCount),
	test_fun_x_times_parallel(stats_io, FunIO, ParCount, SeqCount),
	test_fun_x_times_parallel(stats_wall_clock, FunWallClock, ParCount,
SeqCount),
	test_fun_x_times_parallel(stats_runtime, FunRuntime, ParCount,
SeqCount),
	test_fun_x_times_parallel(stats_reductions, FunReductions, ParCount,
SeqCount),
	test_fun_x_times_parallel(stats_cont_switch, FunContextSwitches,
ParCount, SeqCount),
	test_fun_x_times_parallel(random_uniform, FunRandomUniform, ParCount,
SeqCount),
	test_fun_x_times_parallel(process_info_reduc, FunProcessInfoRed,
ParCount, SeqCount),
	test_fun_x_times_parallel(phash2_io, FunPhashIO, ParCount, SeqCount),
	test_fun_x_times_parallel(stats_io_scaled, FunIOScaled, ParCount,
SeqCount),
	ok.


test_fun_x_times_parallel(Name, Fun, ParCount, SeqCount) ->
	Tick = now(),
	app_util:pmap(
				fun(_) ->
					lists:foreach(fun(_) ->
						Fun()
					end,
					lists:seq(1, SeqCount))
				end,
				lists:seq(1, ParCount),
				[],
				250000),
	Tock = now(),
	AvgTime = timer:now_diff(Tock, Tick)/1000,
	Speed = ParCount*SeqCount*1000/AvgTime,
	io:format("~20w req/sec ~10.1f ~n", [Name, Speed]),
	Speed.


pmap(Fun, List, Nodes, Timeout) ->
	SpawnFun =
		case length(Nodes) of
			0 ->
				fun spawn/1;
			Length ->
				NextNode = fun() -> lists:nth(random:uniform(Length), Nodes) end,
				fun(F) -> spawn(NextNode(), F) end
		end,
	Parent = self(),
	Pids =
		[
			SpawnFun(fun() -> Parent ! {self(), (catch Fun(Elem))} end)
			|| Elem <- List
		],
	[
		receive
			{Pid, Val} -> Val
		after Timeout ->
			exit(timeout)
		end
		|| Pid <- Pids
	].


More information about the erlang-questions mailing list