• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Gen server
 

Gen server

on

  • 25 views

 

Statistics

Views

Total Views
25
Views on SlideShare
25
Embed Views
0

Actions

Likes
1
Downloads
0
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Gen server Gen server Presentation Transcript

    • gen_server сервер внутри сервера Юра Жлоба для Belarus Erlang User Group
    • Все изучали, все знают, все используют. Понимание требует некоторых усилий. Чтобы понять, лучше всего написать gen_server самому :)
    • Описан во-всех книгах по Erlang Джо Армстронг “Programming Erlang”, 16-я глава Фред Хеберт “LYSE”, глава “What is OTP?”
    • Базовый паттерн OTP supervisor, gen_event, gen_fsm реализованы аналогично, но узко специализированны.
    • Приложение stdlib /usr/local/lib/erlang/lib/stdlib-1.19.4
    • gen_server http://www.erlang.org/doc/man/gen_server.html proc_lib http://www.erlang.org/doc/man/proc_lib.html sys http://www.erlang.org/doc/man/sys.html gen не документирован
    • gen_server:start_link(...)
    • gen_server:call(...)
    • gen_server:cast(...)
    • gen_server API start_link/3, start_link/4, start/3, start/4
    • Callback функции init блокирует родительский процесс timeout = infinity должна быть легковесной не должна крашиться :)
    • Callback функции init отложенная инициализация, вариант 1 init(Args) -> State = ... self() ! heavy_init, {ok, State}. handle_info(heavy_init, State) -> NewState = ... {noreply, NewState};
    • Callback функции init отложенная инициализация, вариант 2 init(Args) -> State = ... {ok, State, 0}. handle_info(timeout, State) -> NewState = ... {noreply, NewState};
    • Callback функции handle_call 8 вариантов ответа
    • Callback функции {reply, Reply, NewState} {reply, Reply, NewState, Timeout} {reply, Reply, NewState, hibernate} {noreply, NewState} {noreply, NewState, Timeout} {noreply, NewState, hibernate} {stop, Reason, Reply, NewState} {stop, Reason, NewState}
    • Callback функции handle_call(...) -> gen_server:reply(From, Reply), … {noreply, NewState}
    • Callback функции handle_cast, handle_info 4 варианта ответа
    • Callback функции {noreply, NewState} {noreply, NewState, Timeout} {noreply, NewState, hibernate} {stop, Reason, NewState}
    • Callback функции format_status формирует crash report
    • Callback функции [{data, [{"State", State}]}], [{data, [{"State", get_important_part_of(State)}]},
    • Timeout & hibernate init handle_call handle_cast handle_info
    • Timeout & hibernate init(Args) -> State = ..., {ok, State, 5 * 60 * 1000}. handle_info(timeout, State) -> io:format("~p no messages", [?MODULE]), {noreply, State, hibernate}.
    • Timeout & hibernate Hibernate Процесс занимает минимум памяти: - отбрасывается стек - проводится сборка мусора - дефрагметируется куча
    • Timeout & hibernate Hibernate Процесс редко получает сообщения, большую часть времени проводит в ожидании.
    • Отладка с помощью sys > sys:trace(e_prof, true). ok > e_prof:add_action("some", 5). *DBG* e_prof got cast {add_action,"some",5} *DBG* e_prof new state {state,[{action_accum,[115,111,109,101],[5]}], [{action_stat_set,{16,15,4},[]},{action_stat_set,{16,14,4},[]}, {action_stat_set,{16,13,4},[]},{action_stat_set,{16,12,4},[]}, {action_stat_set,{16,11,4},[]}]} ok > e_prof:add_action("some", 15). *DBG* e_prof got cast {add_action,"some",15} *DBG* e_prof new state {state,[{action_accum,[115,111,109,101], [15,5]}],[{action_stat_set,{16,15,4},[]},{action_stat_set,{16,14,4}, []},{action_stat_set,{16,13,4},[]},{action_stat_set,{16,12,4},[]}, {action_stat_set,{16,11,4},[]}]} ok > sys:trace(e_prof, false). ok sys:trace(Name, Flag)
    • Отладка с помощью sys > sys:statistics(e_prof, true). ok > sys:statistics(e_prof, get). {ok,[{start_time,{{2014,6,18},{16,14,43}}}, {current_time,{{2014,6,18},{16,17,10}}}, {reductions,360}, {messages_in,5}, {messages_out,0}]} > sys:statistics(e_prof, false). ok sys:statistics(Name, Flag)
    • Отладка с помощью sys > sys:get_state(e_prof). {state,[], [{action_stat_set,{16,21,4},[]}, {action_stat_set,{16,20,4},[]}, {action_stat_set,{16,19,4},[]}, {action_stat_set,{16,18,4},[]}, {action_stat_set,{16,17,4},[]}]} sys:get_state(Name) -> State
    • Отладка с помощью sys > sys:get_status(e_prof). {status,<0.136.0>, {module,gen_server}, [[{'$ancestors',[e_prof_sup,<0.134.0>]}, {'$initial_call',{e_prof,init,1}}], running,<0.135.0>, [{statistics,{{{2014,6,18},{16,14,43}}, {reductions,3590}, 4,0}}], [{header,"Status for generic server e_prof"}, {data,[{"Status",running}, {"Parent",<0.135.0>}, {"Logged events",[]}]}, {data,[{"State", {state,[], [{action_stat_set,{16,16,4}, [{action_stat,"some",10.0,15,...}]}, {action_stat_set,{16,15,4},[]}, {action_stat_set,{16,14,4},[]}, {action_stat_set,{16,13,4},[]}, {action_stat_set,{16,12,...},[]}]}}]}]]} sys:get_status(Name) -> Status
    • Оптимизация производительности Всем нам хочется узнать, где и как можно похачить gen_server, чтобы работало быстрее :)
    • Оптимизация производительности Луик Хоген (Loïc Hoguin) основатель компании 99s и автор Cowboy доклад на Erlang Factory 2013 Beyond OTP
    • Оптимизация производительности Так что можно сделать с gen_server?
    • Оптимизация производительности Так что можно сделать с gen_server? - убрать поддержку удаленных узлов
    • Оптимизация производительности Так что можно сделать с gen_server? - убрать поддержку удаленных узлов - убрать proc_lib:sync_wait и {ack, Pid, Result}
    • Оптимизация производительности Так что можно сделать с gen_server? - убрать поддержку удаленных узлов - убрать proc_lib:sync_wait и {ack, Pid, Result} - убрать обработку исключений try...catch
    • Оптимизация производительности Так что можно сделать с gen_server? - убрать поддержку удаленных узлов - убрать proc_lib:sync_wait и {ack, Pid, Result} - убрать обработку исключений try...catch - убрать monitor/demonitor
    • Оптимизация производительности Так что можно сделать с gen_server? - убрать поддержку удаленных узлов - убрать proc_lib:sync_wait и {ack, Pid, Result} - убрать обработку исключений try...catch - убрать monitor/demonitor - не поддерживать Timeout и hibernate
    • Оптимизация производительности Можно на 10-20% увеличить производительность, пожертвовав надежностью.
    • Оптимизация производительности Стоит оно того? Если да, то читайте про special processes в документации, смотрите примеры и делайте
    • Special processes На них построена инфраструктура OPT gen_server, gen_*, supervisor – это все они cоздаются через proc_lib:start_link
    • Special processes Хранят инфу о родительских процессах поддерживают отладку через sys отвечают на системные сообщения
    • Рекомендации по gen_server init должен быть простым и быстрым тяжелую инициализацию делаем отложено не крашимся :)
    • Рекомендации по gen_server “catch all” для всех handle_call, handle_cast, handle_info пишем в лог вместо того, чтобы крашится и терять состояние
    • Рекомендации по gen_server избегаем timeout = infinity это затрудняет диагностику dead lock
    • Рекомендации по gen_server используем call только когда действительно нужен ответ cast быстрее и не блокирует клиентский процесс
    • Рекомендации по gen_server my_server ! Msg handle_info(Msg, State) плохой стиль
    • Рекомендации по gen_server init – конструктор terminate – деструктор освобождайте ресурсы дайте terminate достаточно времени
    • Рекомендации по gen_server -spec для handle_* громоздкий и не нужный не помогает ни как документация ни как опора для dialyzer
    • Рекомендации по gen_server -spec для handle_* но если хотите, то у меня есть удобное решение :)
    • Вопросы?
    • Мой блог yzh44yzh.by