<html>
<head>
<meta content="text/html; charset=windows-1252"
http-equiv="Content-Type">
</head>
<body text="#000000" bgcolor="#FFFFFF">
Looks like you measure the latency of send + dict:find + receive<br>
that sometimes happens to get preemted by very heavy calls<br>
to lists:delete.<br>
<br>
/Sverker<br>
<br>
<br>
<div class="moz-cite-prefix">On 08/22/2016 10:35 AM, Park, Sungjin
wrote:<br>
</div>
<blockquote
cite="mid:CAP6n5fCuGec_cv71MXYQF=YSgYyBz5K-OLOs8XC9CpWATtwe6A@mail.gmail.com"
type="cite">
<pre wrap="">I observed a strange performance degradation in dict. Let me share the
code I used in the test first.
-module(data).
-export([start_link/1, get/1, get_concurrent/1]).
-export([init/0]).
start_link() ->
proc_lib:start_link(?MODULE, init, []).
init() ->
register(?MODULE, self()),
% Initialize data:
% 0 => [],
% 1 => [1],
% 2 => [1,2]
% ...
Dict = lists:foldl(
fun (Key, Dict0) -> dict:store(Key, value(Key), Dict0) end,
dict:new(), lists:seq(0, 255)
),
proc_lib:init_ack({ok, self()}),
loop(Dict).
value(Key) ->
lists:seq(1, Key).
loop(Dict) ->
receive
{get, Key, From} ->
case dict:find(Key, Dict) of
{ok, Value} -> From ! Value;
error -> From ! undefined
end;
_ ->
ok
end,
loop(Dict).
get(Key) ->
?MODULE ! {get, Key, self()},
receive
Value -> Value
end.
%% Run get N times and return average execution time.
-spec get_concurrent(integer()) -> number().
get_concurrent(N) ->
Profiler = self(),
Workers = [
prof_lib:spawn_link(
fun () ->
Key = erlang:system_time() rem 255,
Result = timer:tc(?MODULE, get, [Key]),
Profiler ! {self(), Result}
end
) || _ <- lists:seq(1, N)
],
Ts = receive_all(Workers, []),
lists:sum(Ts) / length(Ts).
receive_all([], Ts) ->
Ts;
receive_all(Workers, Ts) ->
receive
{Worker, {T, _}} -> receive_all(lists:delete(Worker, Workers), [T |
Ts])
end.
When I ran the test in the shell, I got.
1> data:start_link().
{ok, <0.6497.46>}
2> timer:tc(data, get, [5]).
{23,[1,2,3,4,5]}
I could get a value in 23 microseconds and expected something not too
slower results for concurrent get but,
3> data:get_concurrent(100000).
19442.828
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.
I also tried the same with an ets instead of a dict, but there was no such
performance degradation by the value type.
</pre>
<br>
<fieldset class="mimeAttachmentHeader"></fieldset>
<br>
<pre wrap="">_______________________________________________
erlang-questions mailing list
<a class="moz-txt-link-abbreviated" href="mailto:erlang-questions@erlang.org">erlang-questions@erlang.org</a>
<a class="moz-txt-link-freetext" href="http://erlang.org/mailman/listinfo/erlang-questions">http://erlang.org/mailman/listinfo/erlang-questions</a>
</pre>
</blockquote>
<br>
</body>
</html>