2. Плана не будет!
Причины:
- невозможно впитать язык за два часа, надо
начать на нем писать
- невозможно хорошо рассказать о языке за
два часа и при этом так, чтобы ни у кого не
болела голова
- язык — это просто средство выражения
управления чем-либо, без предметной области
его обсуждать скучно и бесполезно
Скажите «Спасибо, кэп!»
3. Что будет
Поговорим за задачи
Посмотрим, каким боком тут поможет Э
Накачаемся кучей фактов
...в надежде, что потом это пригодится в
реальной жизни
OMG!!! Это же план!
4. Поговорим за «тяжелые приложения»
• термина highload не существует, его придумал
Бунин
• буржуины оперируют другими терминами
• High Avaibility Systems (HA) — это любые системы
с 24/7 и кучей девяток в конце (сюда же и вэбня);
• High Performance Computing (HPC) — это уже
про вычисления, съедающие ресурсы без остатка;
• наверное, есть что-то еще... но нам пока хватит
5. Поговорим за HPC
- много потолков (CPU bound, memory bound,
IO bound);
- предметная область — непростая;
- область решений — еще более непростая;
- цель: максимальная производительность,
минимальная задержка;
- 24/7 — как обычно;
- выжать из железа все возможное (цена +1U
может быть больше стоимости времени разработчика на
оптимизацию).
Примеры: HFT, OLAP, video encoding, DPI.
6. Своя особая атмосфера
● ядро (kernel), брысь с моего ядра (core) — cpu
affinity... но нам нужны таймеры и системные вызовы;
● память (преаллокация и локальность, huge
pages, NUMA, пулы структур (слябы), zero
copy, DMA, дружественность кешу);
● выполнение (считаем такты, особенности
компилятора и прыжки в ассемблер,
неблокирующие алгоритмы, минимум
системных вызовов, контролируем
вымывание кеша, помогаем предсказателю
ветвления);
...
7. Своя особая атмосфера - 2
...
● контр-интуитивные знания и опыт (будет ли аппаратно
подпружиненная функция быстрее самописной,
HyperThreading — плохо, и т.д.);
● NIH — это нормально (переписанное и написанное
самостоятельно будет наверняка быстрее и лучше
вписываться в экосистему проекта);
● ЗБЧ. Когда операция повторяется миллиард раз,
выигрыш в миллисекунду приносит неиллюзорный
бенефит;
● языки: С/C++ с подпорками и asm {} (без вариантов);
● спецоборудование (CUDA/OpenCL видео-карты, Xeon
Phi, TileGX, FPGA).
8. А что вы будете делать, если дойдете до конца?
Упираемся головой в одну из границ?
- рост вглубь (смотрим что еще подкрутить);
- рост вширь (добавляем ресурсов).
2 CPU x 8 core + 348GB RAM + 6 x 4Tb— и пока все, что
можно упихать в 1U.
Можно — больше, но это уже свое железо, свои патчи к
ядру, свое производство, свой саппорт, в общем — ну его
нафик...
Остается только одно — ставить еще одну железку. И еще
одну... И еще...
9. Мухи от котлет
- этим безобразием надо как-то управлять
(сообщать конфигурацию)
- за этим безобразием надо как-то следить
(собирать статистику)
Application
Control plane
Data plane
10. А теперь немного уличной магии...
Если с Data plane все ясно, то с Control plane мы можем
развлекаться:
● можно использовать язык высокого уровня;
● легкий FFI с языком data plane;
● сетевая прозрачность/простота;
● легкость интеграции.
● можно использовать сторонние
библиотеки/GC/кеды/смузи;
● можно (но не нужно) падать и терять данные (главное
— не уронить data plane при этом)
● при этом не мешало бы горячая смена кода, если вдруг
понадобятся бантики (а они понадобятся).
11. И где тут Эрланг?
Легкие процессы, нет классической смены
контекста и ее тяжести;
Непростой, но вполне понятный FFI с Си (порты,
NIF, C node);
Сетевая прозрачность и распределенный
характер;
Иммутабельность и GC;
Интроспекция и легкое чтение кода;
24/7: let it fall, hot code reload;
Интегрируемость (ASN.1, куча сетевых сервисов и binary
pattern matching).
12. Берем Э, ставим в продакшен … PROFIT!!
*
* - на самом деле нет.
Нужно еще понимание, что там под капотом:
- OTP (Open Telecom Platform)
- не OTP (bad idea but embeed!)
.erl + .hrl
erlc
.app
.beam
.b.ebaemam
ERTS EPMD
node@localhost
EPMD
EPMD
EPMD
13. Декларативность и pattern matching
- программа не последовательность действий,
а набор правил
- какое правило сработало — то и выполняем
- т.е. такой большой неявный switch/case
(clause, слоз, набор правил)
Соответствие образцу (pattern matching) +
присвоение (про иммутабельность позже):
- полное
{ok, Result} = {ok, [1,2,3]} | {ok, undefined}
- частичное
{error, _} = {error, notfound} | {error, <<123, 255>>}
- с допусловиями (guards)
{ok, IP} where IP =/= {127, 0, 0, 1}
14. Иммутабельность и GC
1> P = 1.
1
2> P = 2.
** exception error: no match of right hand side value 2
vs.
irb(main):001:0> a = 1
=> 1
irb(main):002:0> a = 2
=> 2
irb(main):003:0> print a
2=> nil
+ все версии значения переменной;
+ чужой код не подменит значения;
+ warnings рулят! (возникают
зачастую из-за ошибки);
+ простота GC (собираем по выходу
за границы видимости).
- работа с большими списками и
кортежами — ад копирования и
фрагментация памяти;
- разработчику трудно
адаптироваться;
- имена кончаются, а нумерация
усложняет понимание и написание;
- можно наступить в утечку.
15. Легкие процессы? Wut?
- process vs. threads vs. green threads vs. erlang processes
- не процесс, но объект, инкапсулирующий состояние
(ObjC)
- OTP — инфраструктура над процессами (супервизоры,
серверы, конечные автоматы, события, мониторы)
ppaarreenntt инициализация receive
State
spawn(Fun)
Pid = <0.0 10>
{...}
State
{...}
{...}
State
Fun
309 w (heap: 233)
Pid ! Message
mailbox
16. Let if fall, hot code reload..
- let it fall =/= можно писать с ошибками
- let it fall =:= «ошибки неизбежны, подстрахуемся на их счет»
Страховка: OTP-инфраструктура, супервизоры, мониторы
- немного о релизах
- горячее обновление: останавливаем мир, трансформируем
состояние, меняем код, запускаем мир
- система даже не заметит
- и можно делать по сети
- минусы: надо делать аккуратно, надо следить за версиями
структур и писать трансформеры
- практика: все предпочитают перезагрузится, для вэба это
некритично
18. Интегрируемость
Что уже есть и прям можно брать:
- SNMP, SSH, SSL, telnet, ASN.1 — в комплекте;
- LDAP, HTTP (classic + WS), XMPP, AMQP — стороннее;
- адаптерты к БД (epgsql, eredis, sqlite) — полно;
- ZMQ, GTK, OpenGL — и это тоже, да.
Через ports и NIF можно подпихнуть что угодно:
- библиотеки;
- unix pipes;
- shared memory.
19. Фу-фу-фу
- корявый синтаксис (надо привыкнуть);
- особенности GC и масштабирования;
- небыстрая математика;
- проблема первого пня.
20. Пссс... Хочешь немного кода?
connect(_Con) -> undefine.
msg(Con, <<"I">>, undefine) -> add(Con);
msg(Con, <<"L:", Nick/binary>>, undefine) ->
case enter(Con, Nick) of
{ok, UState} -> UState;
error -> undefine
end;
msg(Con, <<"P">>, S) when S =/= undefine -> pub(Con, S);
msg(Con, <<"S">>, S) when S =/= undefine -> stop(Con, S);
msg(Con, <<"C:", Msg/binary>>, S) when S =/= undefine -> chat(Con, S, Msg);
msg(_, _, S) -> S.
close(Con, S) -> rm(Con, S).
21. Нафик код, архитектура лучше.
Что нужно сделать, чтобы передать статистику работы data plane в
control plane?
Варианты:
1. data plane сам формирует статистику и передает ее в control plane
по шине сообщений;
DP CP
2. control plane сам забирает статистику из разделяемой памяти data
plane;
DP CP
3. data plane готовит статистику по запросу из control plane.
DP CP DP CP