27
Erlang data operation caveats FunBox Илья Аверьянов

Erlang data operation caveats

Embed Size (px)

DESCRIPTION

General mistakes often made by developers new to Erlang

Citation preview

Page 1: Erlang data operation caveats

Erlang data operation

caveats

FunBox

Илья Аверьянов

Page 2: Erlang data operation caveats

1. Deadlocks

Page 3: Erlang data operation caveats

Обращение к самому себе

%%% blacklist.erl

handle_call(get_all_blacklisted, _From, #st{all_blacklisted = AllBlacklisted} = St) ->

{reply, AllBlacklisted, St};...handle_call({is_blacklisted, Word}, _From, St) ->

AllBlacklisted = gen_server:call(blacklist, get_all_blacklisted),IsBlacklisted = lists:any(fun(W) -> W =:= Word end, AllBlacklisted),{reply, IsBlacklisted, St};

Page 4: Erlang data operation caveats

Взаимное обращение%%% processor.erl...handle_call({process_job, Job}, _From, St) ->

do_job(Job),gen_server:call(generator, {register_completion, Job}),{reply, true, St};

%%% generator.erl...handle_call(generate_job, _From, St) ->

Job = generate_job(),gen_server:call(generator, {process_job, Job}),{reply, true, St};

Page 5: Erlang data operation caveats

Бесконечный timeout

gen_server:call(Pid, Message, infinity)

gen_server:call(Pid, Message, 10000)

gen_server:call(Pid, Message)

Page 6: Erlang data operation caveats

Как найти?

erlang:system_info(procs)

Page 7: Erlang data operation caveats

2. Bottlenecks

Page 8: Erlang data operation caveats

2.1. Явные bottleneck-и

Page 9: Erlang data operation caveats

Медленные операции в gen_server

handle_call({calculate_pi, Digits}, _From, St) ->Pi = calculate_pi(Digits),{reply, Pi, St};

handle_call({get_new_files_from_bbs, Boss}, _From, St) ->Files = get_new_files_from_bbs(Boss), {reply, Files, St};

Page 10: Erlang data operation caveats

Лишнее копирование данных

Плохо

is_blacklisted(Word) ->AllBlacklisted = gen_server:call(BlackListPid, get_all_blacklisted),sets:is_element(Word, AllBlacklisted).

handle_call(get_all_blacklisted, _From, #st{all_blacklisted = AllBlacklisted} = St) ->

{reply, AllBlacklisted, St};

Page 11: Erlang data operation caveats

Хорошо

is_blacklisted(Word) ->AllBlacklisted = gen_server:call({is_blacklisted, Word}).

handle_call({is_blacklisted, Word}, _From, #st{all_blacklisted = AllBlacklisted} = St)

Result = sets:is_element(Word, AllBlacklisted).{reply, Result, St};

Page 12: Erlang data operation caveats

Документация!

● http://www.erlang.org/doc/efficiency_guide/processes.html

● Refc binaries (не копируются между процессами в рамках одной

виртуальной машины)

● Heap binaries (<= 64 bytes)

● ets и dets

Page 13: Erlang data operation caveats

2.2 Неявные bottleneck-и

Page 14: Erlang data operation caveats

Плохо

handle_cast(incr, St = #st{redis = Redis}) ->

spawn_link(fun() -> redis:qp(Redis, "INCR key") end).

St.

Page 15: Erlang data operation caveats

3. Лишнее копирование

См. 2.1.

Page 16: Erlang data operation caveats

Более хитрый пример

handle_deliver_sm(Pdu, {Pid, _}, #st{smsc_monitor_pid = SmscMonitorPid} = St) ->smsc_monitor:event(deliver_sm, SmscMonitorPid),event_counter:event(esme_client_deliver_sm),do_handle_deliver_sm(Pid, Pdu, St),{reply, noreply, St}.

Page 17: Erlang data operation caveats

handle_deliver_sm(Pdu, {Pid, _}, #st{smsc_monitor_pid = SmscMonitorPid} = St) ->smsc_monitor:event(deliver_sm, SmscMonitorPid),event_counter:event(esme_client_deliver_sm),spawn_link(fun() -> do_handle_deliver_sm(Pid, Pdu, St) end),{reply, noreply, St}.

Page 18: Erlang data operation caveats
Page 19: Erlang data operation caveats

handle_deliver_sm(Pdu, {Pid, _}, #st{smsc_monitor_pid = SmscMonitorPid} = St) ->smsc_monitor:event(deliver_sm, SmscMonitorPid),event_counter:event(esme_client_deliver_sm),spawn_link(fun() -> do_handle_deliver_sm(Pid, Pdu, St) end),{reply, noreply, St}.

Page 20: Erlang data operation caveats

handle_deliver_sm(Pdu, {Pid, _}, #st{smsc_monitor_pid = SmscMonitorPid} = St) ->smsc_monitor:event(deliver_sm, SmscMonitorPid),event_counter:event(esme_client_deliver_sm),LightSt = St#st{reqs = undefined},spawn_link(fun() -> do_handle_deliver_sm(Pid, Pdu, LightSt) end),{reply, noreply, St}.

Page 21: Erlang data operation caveats

Как бороться

● Передавать в процесс только необходимые ему данные (в рамках

функционального стиля)

● Не делать по возможности спаун линк, а использовать другой

gen_server с пулом воркеров к нему

Page 22: Erlang data operation caveats

3. Memory leaks

Локально

gen_server:cast(LocalPiCalcPid, {calculate_pi, Digits}).

Page 23: Erlang data operation caveats

На удаленной машине

gen_server:cast({PiCalcPid, remote@node}, {calculate_pi, Digits}).

Page 24: Erlang data operation caveats

Как найти и побороть

process_info(Pid),

process_info(Pid, memory)

Page 25: Erlang data operation caveats

4. IO

Плохо

case process_job(Job) of{ok, Res} ->

send_job_result(Res);{error, some_noncritical_frequent_error} ->

lager:error(“Error: some_noncritical_frequent_error”)end.

Page 26: Erlang data operation caveats

Хорошо

file:open(Path, [append, raw, {delayed_write, ?WRITE_BUFFER_SIZE,

?WRITE_BUFFER_MAX_DELAY}])

Page 27: Erlang data operation caveats

5. Недостаток ресурсов

● erl +P 1048576

● ulimit -n

● no swap!