Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(gproc_pool): fix
rand:uniform/1
range (#193)
Since [`rand:uniform/1`](https://www.erlang.org/doc/man/rand.html#uniform-1)'s return value is a number in a closed interval (`0 =< N =< Sz`), we shouldn't call it with the pool size + 1, otherwise we will get a non-uniform distribution of results where one of the workers receive substantially more work than all others. To verify this, I've started a pool with 8 workers using the `random` load-balancing algorithm and measured the frequencies of each PID in `gproc_pool`. ```erlang PoolName = my_pool. PoolSize = 8. ok = gproc_pool:new(PoolName, random, [{size, PoolSize}]). lists:foreach(fun(I) -> gproc_pool:add_worker(PoolName, {PoolName, I}, I), spawn(fun() -> true = gproc_pool:connect_worker(PoolName, {PoolName, I}), receive stop -> ok end end), ok end, lists:seq(1, PoolSize)). MeasureFreqs = fun(Pool, NumPoints) -> Pids = lists:map(fun(_) -> gproc_pool:pick_worker(Pool) end, lists:seq(1, NumPoints)), lists:foldl( fun(Pid, Acc) -> maps:update_with(Pid, fun(N) -> N + 1 end, 1, Acc) end, #{}, Pids ) end. MeasureFreqs(PoolName, 100_000). ``` Results prior to the fix (note how `<0.172.0>` has almost double the frequency of other PIDs): ```erlang #{<0.172.0> => 22222,<0.173.0> => 11138,<0.174.0> => 11000, <0.175.0> => 11046,<0.176.0> => 11141,<0.177.0> => 11165, <0.178.0> => 11166,<0.179.0> => 11122} ``` After the fix: ```erlang #{<0.172.0> => 12460,<0.173.0> => 12367,<0.174.0> => 12541, <0.175.0> => 12494,<0.176.0> => 12649,<0.177.0> => 12399, <0.178.0> => 12439,<0.179.0> => 12651} ```
- Loading branch information