<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>