pooler_perf_test.erl 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. -module(pooler_perf_test).
  2. -compile([export_all]).
  3. -include_lib("eunit/include/eunit.hrl").
  4. -define(gv(X, L), proplists:get_value(X, L)).
  5. setup() ->
  6. setup(10, 100, 5).
  7. setup(InitCount, MaxCount, NumPools) ->
  8. MakePool = fun(I) ->
  9. N = integer_to_list(I),
  10. Name = "p" ++ N,
  11. Arg0 = "pool-" ++ Name,
  12. [
  13. {name, list_to_atom(Name)},
  14. {max_count, MaxCount},
  15. {init_count, InitCount},
  16. {start_mfa, {pooled_gs, start_link, [{Arg0}]}}
  17. ]
  18. end,
  19. Pools = [MakePool(I) || I <- lists:seq(1, NumPools)],
  20. application:set_env(pooler, pools, Pools),
  21. application:start(pooler).
  22. consumer_cycle(N) ->
  23. consumer_cycle(N, 0, 0).
  24. consumer_cycle(N, NumOk, NumFail) when N > 0 ->
  25. P = pooler:take_member(p1),
  26. case P of
  27. Pid when is_pid(Pid) ->
  28. true = is_process_alive(P),
  29. pooler:return_member(p1, P, ok),
  30. consumer_cycle(N - 1, NumOk + 1, NumFail);
  31. _ ->
  32. consumer_cycle(N - 1, NumOk, NumFail + 1)
  33. end;
  34. consumer_cycle(0, NumOk, NumFail) ->
  35. [{ok, NumOk}, {fail, NumFail}].
  36. test1() ->
  37. N = 10000,
  38. {Time, _} = timer:tc(
  39. fun() ->
  40. consumer_cycle(N)
  41. end,
  42. []
  43. ),
  44. Time / N.
  45. consumer_worker(N, Parent) ->
  46. spawn(fun() ->
  47. Parent ! {self(), consumer_cycle(N)}
  48. end).
  49. test3(W, N) ->
  50. [consumer_worker(W, self()) || _I <- lists:seq(1, N)].
  51. test2(Iter, Workers) ->
  52. Self = self(),
  53. {Time, Res} =
  54. timer:tc(
  55. fun() ->
  56. Pids = [
  57. consumer_worker(Iter, Self)
  58. || _I <- lists:seq(1, Workers)
  59. ],
  60. gather_pids(Pids)
  61. end,
  62. []
  63. ),
  64. {NumOk, NumFail} = lists:foldr(
  65. fun({_, L}, {O, F}) ->
  66. {O + ?gv(ok, L), F + ?gv(fail, L)}
  67. end,
  68. {0, 0},
  69. Res
  70. ),
  71. {Time, [{ok, NumOk}, {fail, NumFail}]}.
  72. gather_pids(Pids) ->
  73. gather_pids(Pids, []).
  74. gather_pids([Pid | Rest], Acc) ->
  75. receive
  76. {Pid, Ans} ->
  77. gather_pids(Rest, [{Pid, Ans} | Acc]);
  78. stop ->
  79. stop
  80. end;
  81. gather_pids([], Acc) ->
  82. Acc.
  83. pooler_take_return_test_() ->
  84. {foreach,
  85. % setup
  86. fun() ->
  87. InitCount = 100,
  88. MaxCount = 100,
  89. NumPools = 5,
  90. logger:set_handler_config(default, filters, []),
  91. setup(InitCount, MaxCount, NumPools)
  92. end,
  93. fun(_X) ->
  94. application:stop(pooler)
  95. end,
  96. [
  97. {"take return cycle single worker", fun() ->
  98. NumCycles = 10000,
  99. Ans = consumer_cycle(NumCycles),
  100. ?assertEqual(NumCycles, ?gv(ok, Ans)),
  101. ?assertEqual(0, ?gv(fail, Ans))
  102. end},
  103. {"take return cycle multiple workers", fun() ->
  104. Self = self(),
  105. Iter = 100,
  106. Workers = 100,
  107. Pids = [
  108. consumer_worker(Iter, Self)
  109. || _I <- lists:seq(1, Workers)
  110. ],
  111. Res = gather_pids(Pids),
  112. {NumOk, NumFail} =
  113. lists:foldr(
  114. fun({_, L}, {O, F}) ->
  115. {O + ?gv(ok, L), F + ?gv(fail, L)}
  116. end,
  117. {0, 0},
  118. Res
  119. ),
  120. %% not sure what to test here now. We expect some
  121. %% failures if init count is less than max count
  122. %% because of async start.
  123. ?assertEqual(0, NumFail),
  124. ?assertEqual(100 * 100, NumOk)
  125. end}
  126. ]}.