erlang data operation caveats

Post on 08-Jul-2015

253 Views

Category:

Software

3 Downloads

Preview:

Click to see full reader

DESCRIPTION

General mistakes often made by developers new to Erlang

TRANSCRIPT

Erlang data operation

caveats

FunBox

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

1. Deadlocks

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

%%% 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};

Взаимное обращение%%% 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};

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

gen_server:call(Pid, Message, infinity)

gen_server:call(Pid, Message, 10000)

gen_server:call(Pid, Message)

Как найти?

erlang:system_info(procs)

2. Bottlenecks

2.1. Явные bottleneck-и

Медленные операции в 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};

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

Плохо

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

Хорошо

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

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

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

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

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

● Heap binaries (<= 64 bytes)

● ets и dets

2.2 Неявные bottleneck-и

Плохо

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

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

St.

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

См. 2.1.

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

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

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

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

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

Как бороться

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

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

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

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

3. Memory leaks

Локально

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

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

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

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

process_info(Pid),

process_info(Pid, memory)

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.

Хорошо

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

?WRITE_BUFFER_MAX_DELAY}])

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

● erl +P 1048576

● ulimit -n

● no swap!

top related