<div dir="ltr">I observed a strange performance degradation in dict. Let me share the code I used in the test first.<div><br></div><div><br></div><div>  -module(data).</div><div>  -export([start_link/1, get/1, get_concurrent/1]).</div><div>  -export([init/0]).</div><div><br></div><div>  start_link() -></div><div>   proc_lib:start_link(?MODULE, init, []).</div><div><br></div><div>  init() -><br></div><div>   register(?MODULE, self()),</div><div>   % Initialize data:</div><div>   % 0 => [],</div><div>   % 1 => [1],</div><div>   % 2 => [1,2]</div><div>   % ...</div><div>   Dict = lists:foldl(</div><div>    fun (Key, Dict0) -> dict:store(Key, value(Key), Dict0) end,</div><div>    dict:new(), lists:seq(0, 255)</div><div>   ),</div><div>   proc_lib:init_ack({ok, self()}),</div><div>   loop(Dict).</div><div><br></div><div>  value(Key) -></div><div>    lists:seq(1, Key).</div><div><br></div><div>  loop(Dict) -><br></div><div>   receive</div><div>    {get, Key, From} -></div><div>     case dict:find(Key, Dict) of</div><div>      {ok, Value} -> From ! Value;</div><div>      error -> From ! undefined</div><div>     end;</div><div>    _ -></div><div>     ok</div><div>   end,</div><div>   loop(Dict).</div><div><br></div><div>  get(Key) -><br></div><div>   ?MODULE ! {get, Key, self()},</div><div>   receive</div><div>    Value -> Value</div><div>   end.</div><div><br></div><div>  %% Run get N times and return average execution time.</div><div>  -spec get_concurrent(integer()) -> number().</div><div>  get_concurrent(N) -></div><div>   Profiler = self(),</div><div>   Workers = [</div><div>     prof_lib:spawn_link(</div><div>      fun () -></div><div>       Key = erlang:system_time() rem 255,</div><div>       Result = timer:tc(?MODULE, get, [Key]),</div><div>       Profiler ! {self(), Result}</div><div>      end</div><div>     ) || _ <- lists:seq(1, N)</div><div>    ],</div><div>    Ts = receive_all(Workers, []),</div><div>    lists:sum(Ts) / length(Ts).</div><div><br></div><div>  receive_all([], Ts) -></div><div>   Ts;</div><div>  receive_all(Workers, Ts) -></div><div>   receive</div><div>    {Worker, {T, _}} -> receive_all(lists:delete(Worker, Workers), [T | Ts])</div><div>   end.</div><div><br></div><div><br></div><div>When I ran the test in the shell, I got.</div><div><br></div><div>  1> data:start_link().<br></div><div>  {ok, <0.6497.46>}</div><div>  2> timer:tc(data, get, [5]).</div><div>  {23,[1,2,3,4,5]}</div><div><br></div><div><br></div><div>I could get a value in 23 microseconds and expected something not too slower results for concurrent get but,</div><div><br></div><div>  3> data:get_concurrent(100000).</div><div>  19442.828</div><div><br></div><div><br></div><div>The value 19442.828 microseconds seemed to be too big a value so I tested with different values such as large binaries and tuples. And this time the same get_concurrent(100000) gave me 200 something microseconds.</div><div><br></div><div>I also tried the same with an ets instead of a dict, but there was no such performance degradation by the value type.</div><div><br></div><div>-- <br><div class="gmail_signature" data-smartmail="gmail_signature">Park, Sungjin<div>-------------------------------------------------------------------------------------------------------------------</div><div>Peculiar travel suggestions are dancing lessons from god.</div><div> -- The Books of Bokonon</div><div>-------------------------------------------------------------------------------------------------------------------</div></div>
</div></div>