SlideShare a Scribd company logo
Баннерокрутилка:
как это было на Erlang
Задача
●   Выдача ссылок на новости
    ●   База из тысяч новостей
    ●   Ссылки выбираются произвольно
    ●   Распределение – неравномерное
●   Форматирование ссылок перед выдачей
    ●   Ссылки должны иметь формат блока
    ●   Дополнительные поля: идентификатор блока, …
Ta-da!
●   Требования: >= 5000 запросов в секунду
    ●   Не справляемся – должны быстро выдавать
        пустую страницу, чтобы не «ломать» вёрстку
    ●   Никакого кэширования
●   Срок выполнения: полтора месяца.
    ●   При этом у разработчика баннерокрутилки
        есть и другие задачи
Структура решения
●   Структуры в памяти, хранящие новости
    и статистику показов
●   Множество потоков, обрабатывающих
    HTTP-запросы

●   Контроллер
    ●   добавляющий и удаляющий новости
    ●   собирающий статистику
    ●   на основе TCP-сокетов
Структура решения


Множество потоков
Erlang
●   DSL для многопоточных приложений
●   Встроенные в язык примитивы для посылки
    и приёма сообщений
●   Встроенные в язык шаблоны поведения
●   Встроенная в язык in-memory БД
Структура решения
●   Структуры в памяти, хранящие новости и
    статистику показов: mnesia/ets/dict!
●   Множество потоков, обрабатывающих HTTP-
    запросы: gen_server!

●   Контроллер: gen_tcp!
Структура решения
●   Структуры в памяти, хранящие новости и
    статистику показов: mnesia/ets/dict!
●   Множество потоков, обрабатывающих HTTP-
    запросы: gen_server!
    ●   который уже написан за нас! mochiweb/misultin
●   Контроллер: gen_tcp!


    Batteries included
Batteries included, though not all
Основная часть решения
●   HTTP-сервер Mochiweb получает запрос,
    создаёт поток
●   Поток забирает из Mnesia данные
●   Поток производит выборку, сортирует
    данные, форматирует строки, выдаёт,
    умирает.
    Все счастливы.


            «In theory, there's no difference between
            theory and practice. In practice, there is».
                           L. A. van der Snepscheut.
Факап #1
    У каждой новости есть коэффициент
    важности. В соответствии с этим
    коэффициентом необходимо выдавать
    новость чаще или реже остальных.

●   Перед выдачей нужно назначать
    взвешенные произвольные числа каждой
    новости и делать по ним выборку.
●   Новостей много.
Факап #1
●   Mnesia построена на основе ETS
●   http://www.erlang.org/doc/man/ets.html:
      «In the current implementation, every object insert
      and look-up operation results in a copy of the
      object.»

●   Т. е. в копировании сотен новостей из потока
    в поток. Slow as hell.
Эврика!
●   Вместо ETS напишем собственную структуру
    данных на основе gen_server, dict, queue,
    blackjack и hookers.
●   Повесим её в виде отдельного потока
●   Будем делать там грубую предвыборку
    новостей, которые потом быстро
    скопируются в рабочий поток
●   Результат:
        рост производительности в 3 раза


●   Вывод:
    ●   всегда думай, какие объёмы данных копируешь!
    ●   профилируй!
Основная часть решения v0.2
●   HTTP-сервер Mochiweb получает запрос,
    создаёт поток
●   Поток отправляет запрос в gen_server
●   gen_server производит предвыборку
    новостей и присылает результат
●   Поток производит выборку, сортирует
    данные, форматирует строки, выдаёт,
    умирает.
    Все счастливы.
Факап #2
    Новости – это текст.
    Текст – это строки.

●   Строки в Erlang – это связные списки
    символов
●   IO в Erlang – это очень медленно
Эврика!
●   Если вы пишете на Erlang,
    то строка символов записывается так:

                  "Hello world!~n"

●   Конкатенация записывается так:

           "Hello " ++ Username ++ "!~n"
Эврика!
●   Если вы пишете на Erlang веб-приложения,
    то строка символов записывается так:

               <<"Hello world!~n">>

●   Конкатенация записывается так:

        [<<"Hello ">>, Username, <<"!~n">>]
Почему:
●   <<>> – встроенный бинарный тип
●   <<"">> – бинарная строка
●   Списки символов нужно обрабатывать
    перед выдачей
●   Вывод бинарных данных – это просто
    вызов writev(2)
    ●   Blazingly Fast
Почему:
●   "Hello" ++ "!n" => "Hello!n" => строка
    ●   Конкатенация списков – O(n)
    ●   Вывод строки => цикл по списку из 7 символов
●   [<<"Hello">>, <<"!n">>] – тип iolist().
    ●   Добавление в начало списка – O(1)
    ●   Вывод => цикл по списку из 2 элементов
    ●   Встроенным функциям I/O всё равно, что
        выводить
Кроме того
●   Строковые операции, наподобие обработки
    регулярных выражений, всё равно дорогие
●   Впрочем, они вообще не очень дешевы.
    Обработку данных нужно делать не на этапе
    выдачи, а на этапе помещения в базу – до
    тех пор, пока позволяют объёмы памяти и
    специфика решаемой задачи.
●   В данном случае кэширование
    конструируемых URL новостей и т. п.
    позволило отыграть 15%
●   Результат:
        рост производительности в 10 (десять) раз


●   Вывод:
    ●   всегда думай, как обрабатывать строки!
    ●   профилируй!
Основная часть решения v0.3
●   HTTP-сервер Mochiweb получает запрос,
    создаёт поток
●   Поток отправляет запрос в gen_server
●   gen_server производит предвыборку
    новостей и присылает результат
●   Поток производит выборку, сортирует
    данные, форматирует iolist()'ы, выдаёт,
    умирает.
профилируй!
Основная часть решения v0.4
●   HTTP-сервер Misultin получает запрос,
    создаёт поток
●   Поток отправляет запрос в gen_server
●   gen_server производит предвыборку
    новостей и присылает результат
●   Поток производит выборку, сортирует
    данные, форматирует iolist()'ы, выдаёт,
    умирает.
Misultin
●   Реализация gen_server, как и Mochiweb
●   Интерфейс, абсолютно аналогичный
    Mochiweb
●   Стабильно на 10-15% быстрее
Результат
●   Один человекомесяц
●   Быстрое веб-приложение

    # ab -qc 7200 -n 450000 http://localhost/block/35237
    | grep Requests per sec
    Requests per second:    7693.35 [#/sec] (mean)
    #
Killing feature!
    Начиная со второй недели разработки (как
    только был написан каркас), приложение
    было готово к работе.
    В любой момент не работал только тот
    функционал, который не был дописан.
●   Ни отладки
●   Ни непредусмотренного поведения
●   Только профилирование
Killing feature!
●   Ни отладки
●   Ни непредусмотренного поведения
    В Erlang есть концепция «Let it crash».
    Близкий перевод – «Ну и хрен с ним».
Let it crash
●   На обычном языке программирования:

    res = web_server.start_link(callback = Fun)

    if res == web_server.port_in_use:
        raise Exception("Port in use")
    elif res == web_server.socket_error:
        raise Exception("Socket error")
    elif res == errno.EACCES:
        raise Exception("Not enough privileges")
Let it crash
●   На Erlang:

    {ok, Pid} = misultin:start_link([{loop, Fun}]).
Let it crash
●   На Erlang:

    {ok, Pid} = misultin:start_link([{loop, Fun}]).


●   Если что-то шандарахнется, то
    предположение
    misultin:start_link/1 => {ok, _}

    окажется неверным, и поток вылетит сам
    с сообщением, например, таким:
    {badmatch, {error, eacces}}
Результат
●   Один человекомесяц
●   Быстрое веб-приложение
●   Стабильное веб-приложение – за счёт eunit
    и «Let it crash»
●   Минимум кода – за счёт множества
    встроенных примитивов и «Let it crash»
●   Минимум требуемого опыта – Erlang
    изучается за 2 недели
Уровень программиста
●   С одной стороны, Erlang учится за 2 недели
●   С другой стороны, нужно иметь навыки
    программирования. Not all batteries included

    Для написания баннерокрутилки в разное время
    требовался то JSON-декодер, то перекодировка из
    UTF8 в CP1251, то htmlspecialchars(). Ничего этого
    в stdlib нет, нужно брать сторонние библиотеки,
    оценивать их работоспособность и
    производительность.
Напутствие
●   Предобрабатывай данные, пока это дёшево!
●   Не выполняй одни и те же операции дважды!
●   Используй «Let it crash» в интерфейсах
    собственного кода!
●   Профилируй!
●   Переписывай медленные операции на C,
    PHP, OCaml, whatever: существуют открытые
    биндинги

More Related Content

What's hot

Database First! О распространённых ошибках использования РСУБД
Database First! О распространённых ошибках использования РСУБДDatabase First! О распространённых ошибках использования РСУБД
Database First! О распространённых ошибках использования РСУБД
Nikolay Samokhvalov
 
Максим Лапшин — введение в Erlang
Максим Лапшин — введение в ErlangМаксим Лапшин — введение в Erlang
Максим Лапшин — введение в Erlang
Александр Ежов
 
ELK: менеджмент логов, быстрая локализация проблем / Сергей Шумов (News360)
ELK: менеджмент логов, быстрая локализация проблем / Сергей Шумов (News360)ELK: менеджмент логов, быстрая локализация проблем / Сергей Шумов (News360)
ELK: менеджмент логов, быстрая локализация проблем / Сергей Шумов (News360)
Ontico
 
Эффективная отладка репликации MySQL / Света Смирнова (Percona)
Эффективная отладка репликации MySQL / Света Смирнова (Percona)Эффективная отладка репликации MySQL / Света Смирнова (Percona)
Эффективная отладка репликации MySQL / Света Смирнова (Percona)
Ontico
 
Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server ...
Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server ...Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server ...
Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server ...
Stas Vyschepan
 
Быстрый рендеринг с DOM шаблонизаторами / Борис Каплуновский (aviasales.ru)
Быстрый рендеринг с DOM шаблонизаторами / Борис Каплуновский (aviasales.ru)Быстрый рендеринг с DOM шаблонизаторами / Борис Каплуновский (aviasales.ru)
Быстрый рендеринг с DOM шаблонизаторами / Борис Каплуновский (aviasales.ru)
Ontico
 
Асинхронная репликация без цензуры, Олег Царёв (Mail.ru Group)
Асинхронная репликация без цензуры, Олег Царёв (Mail.ru Group)Асинхронная репликация без цензуры, Олег Царёв (Mail.ru Group)
Асинхронная репликация без цензуры, Олег Царёв (Mail.ru Group)
Ontico
 
"Мы два месяца долбались, а потом построили индекс" (c) Аксенов
"Мы два месяца долбались, а потом построили индекс" (c) Аксенов"Мы два месяца долбались, а потом построили индекс" (c) Аксенов
"Мы два месяца долбались, а потом построили индекс" (c) Аксенов
Alex Chistyakov
 
#RuPostges в Yandex, эпизод 3. Что же нового в PostgreSQL 9.6
#RuPostges в Yandex, эпизод 3. Что же нового в PostgreSQL 9.6#RuPostges в Yandex, эпизод 3. Что же нового в PostgreSQL 9.6
#RuPostges в Yandex, эпизод 3. Что же нового в PostgreSQL 9.6
Nikolay Samokhvalov
 
#noBackend, или Как выжить в эпоху толстеющих клиентов
#noBackend, или Как выжить в эпоху толстеющих клиентов#noBackend, или Как выжить в эпоху толстеющих клиентов
#noBackend, или Как выжить в эпоху толстеющих клиентов
Nikolay Samokhvalov
 
Опыт использования Erlang в разработке многопользовательской игры
Опыт использования Erlang в разработке многопользовательской игрыОпыт использования Erlang в разработке многопользовательской игры
Опыт использования Erlang в разработке многопользовательской игры
Yuri Zhloba
 
My talk on PgDay Russia 2014
My talk on PgDay Russia 2014My talk on PgDay Russia 2014
My talk on PgDay Russia 2014
Alex Chistyakov
 
Конструктор / Денис Паясь (Яндекс)
Конструктор / Денис Паясь (Яндекс)Конструктор / Денис Паясь (Яндекс)
Конструктор / Денис Паясь (Яндекс)
Ontico
 
JPHP - О проекте на простом языке
JPHP - О проекте на простом языкеJPHP - О проекте на простом языке
JPHP - О проекте на простом языке
Dmitry Zaytsev
 
My talk on administering PostgreSQL
My talk on administering PostgreSQLMy talk on administering PostgreSQL
My talk on administering PostgreSQL
Alex Chistyakov
 
Доклад Виталия Котова на конференции LoveQA. "Selenium тесты. От RC и одного ...
Доклад Виталия Котова на конференции LoveQA. "Selenium тесты. От RC и одного ...Доклад Виталия Котова на конференции LoveQA. "Selenium тесты. От RC и одного ...
Доклад Виталия Котова на конференции LoveQA. "Selenium тесты. От RC и одного ...
Badoo Development
 
CodeFest 2014. Каплуновский Б. — Использование асинхронного I/O для снижения ...
CodeFest 2014. Каплуновский Б. — Использование асинхронного I/O для снижения ...CodeFest 2014. Каплуновский Б. — Использование асинхронного I/O для снижения ...
CodeFest 2014. Каплуновский Б. — Использование асинхронного I/O для снижения ...CodeFest
 
libfpta — обгоняя SQLite и Tarantool / Леонид Юрьев (Positive Technologies)
libfpta — обгоняя SQLite и Tarantool / Леонид Юрьев (Positive Technologies)libfpta — обгоняя SQLite и Tarantool / Леонид Юрьев (Positive Technologies)
libfpta — обгоняя SQLite и Tarantool / Леонид Юрьев (Positive Technologies)
Ontico
 

What's hot (20)

Erlang&rails
Erlang&railsErlang&rails
Erlang&rails
 
Database First! О распространённых ошибках использования РСУБД
Database First! О распространённых ошибках использования РСУБДDatabase First! О распространённых ошибках использования РСУБД
Database First! О распространённых ошибках использования РСУБД
 
Максим Лапшин — введение в Erlang
Максим Лапшин — введение в ErlangМаксим Лапшин — введение в Erlang
Максим Лапшин — введение в Erlang
 
ELK: менеджмент логов, быстрая локализация проблем / Сергей Шумов (News360)
ELK: менеджмент логов, быстрая локализация проблем / Сергей Шумов (News360)ELK: менеджмент логов, быстрая локализация проблем / Сергей Шумов (News360)
ELK: менеджмент логов, быстрая локализация проблем / Сергей Шумов (News360)
 
Эффективная отладка репликации MySQL / Света Смирнова (Percona)
Эффективная отладка репликации MySQL / Света Смирнова (Percona)Эффективная отладка репликации MySQL / Света Смирнова (Percona)
Эффективная отладка репликации MySQL / Света Смирнова (Percona)
 
Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server ...
Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server ...Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server ...
Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server ...
 
Быстрый рендеринг с DOM шаблонизаторами / Борис Каплуновский (aviasales.ru)
Быстрый рендеринг с DOM шаблонизаторами / Борис Каплуновский (aviasales.ru)Быстрый рендеринг с DOM шаблонизаторами / Борис Каплуновский (aviasales.ru)
Быстрый рендеринг с DOM шаблонизаторами / Борис Каплуновский (aviasales.ru)
 
Асинхронная репликация без цензуры, Олег Царёв (Mail.ru Group)
Асинхронная репликация без цензуры, Олег Царёв (Mail.ru Group)Асинхронная репликация без цензуры, Олег Царёв (Mail.ru Group)
Асинхронная репликация без цензуры, Олег Царёв (Mail.ru Group)
 
"Мы два месяца долбались, а потом построили индекс" (c) Аксенов
"Мы два месяца долбались, а потом построили индекс" (c) Аксенов"Мы два месяца долбались, а потом построили индекс" (c) Аксенов
"Мы два месяца долбались, а потом построили индекс" (c) Аксенов
 
#RuPostges в Yandex, эпизод 3. Что же нового в PostgreSQL 9.6
#RuPostges в Yandex, эпизод 3. Что же нового в PostgreSQL 9.6#RuPostges в Yandex, эпизод 3. Что же нового в PostgreSQL 9.6
#RuPostges в Yandex, эпизод 3. Что же нового в PostgreSQL 9.6
 
#noBackend, или Как выжить в эпоху толстеющих клиентов
#noBackend, или Как выжить в эпоху толстеющих клиентов#noBackend, или Как выжить в эпоху толстеющих клиентов
#noBackend, или Как выжить в эпоху толстеющих клиентов
 
Опыт использования Erlang в разработке многопользовательской игры
Опыт использования Erlang в разработке многопользовательской игрыОпыт использования Erlang в разработке многопользовательской игры
Опыт использования Erlang в разработке многопользовательской игры
 
My talk on PgDay Russia 2014
My talk on PgDay Russia 2014My talk on PgDay Russia 2014
My talk on PgDay Russia 2014
 
Конструктор / Денис Паясь (Яндекс)
Конструктор / Денис Паясь (Яндекс)Конструктор / Денис Паясь (Яндекс)
Конструктор / Денис Паясь (Яндекс)
 
JPHP - О проекте на простом языке
JPHP - О проекте на простом языкеJPHP - О проекте на простом языке
JPHP - О проекте на простом языке
 
My talk on administering PostgreSQL
My talk on administering PostgreSQLMy talk on administering PostgreSQL
My talk on administering PostgreSQL
 
Доклад Виталия Котова на конференции LoveQA. "Selenium тесты. От RC и одного ...
Доклад Виталия Котова на конференции LoveQA. "Selenium тесты. От RC и одного ...Доклад Виталия Котова на конференции LoveQA. "Selenium тесты. От RC и одного ...
Доклад Виталия Котова на конференции LoveQA. "Selenium тесты. От RC и одного ...
 
CodeFest 2014. Каплуновский Б. — Использование асинхронного I/O для снижения ...
CodeFest 2014. Каплуновский Б. — Использование асинхронного I/O для снижения ...CodeFest 2014. Каплуновский Б. — Использование асинхронного I/O для снижения ...
CodeFest 2014. Каплуновский Б. — Использование асинхронного I/O для снижения ...
 
libfpta — обгоняя SQLite и Tarantool / Леонид Юрьев (Positive Technologies)
libfpta — обгоняя SQLite и Tarantool / Леонид Юрьев (Positive Technologies)libfpta — обгоняя SQLite и Tarantool / Леонид Юрьев (Positive Technologies)
libfpta — обгоняя SQLite и Tarantool / Леонид Юрьев (Positive Technologies)
 
мир без Jsp. thymeleaf 2.0
мир без Jsp. thymeleaf 2.0мир без Jsp. thymeleaf 2.0
мир без Jsp. thymeleaf 2.0
 

Similar to Баннерокрутилка на Erlang

Continuous Deployment (in Russian)
Continuous Deployment  (in Russian)Continuous Deployment  (in Russian)
Continuous Deployment (in Russian)Smartling
 
Continuous deployment Smartling event
Continuous deployment Smartling eventContinuous deployment Smartling event
Continuous deployment Smartling eventViktoriya Pridatko
 
Romanova techforum bash
Romanova techforum bashRomanova techforum bash
Romanova techforum bashkuchinskaya
 
Другая виртуализация
Другая виртуализацияДругая виртуализация
Другая виртуализация
Yandex
 
Хорошо поддерживаемое в продакшне приложение / Николай Сивко (okmeter.io)
Хорошо поддерживаемое в продакшне приложение / Николай Сивко (okmeter.io)Хорошо поддерживаемое в продакшне приложение / Николай Сивко (okmeter.io)
Хорошо поддерживаемое в продакшне приложение / Николай Сивко (okmeter.io)
Ontico
 
20111002 information retrieval raskovalov_lecture3
20111002 information retrieval raskovalov_lecture320111002 information retrieval raskovalov_lecture3
20111002 information retrieval raskovalov_lecture3Computer Science Club
 
ORM технологии в .NET (Nhibernate, Linq To SQL, Entity Framework)
ORM технологии в .NET (Nhibernate, Linq To SQL, Entity Framework)ORM технологии в .NET (Nhibernate, Linq To SQL, Entity Framework)
ORM технологии в .NET (Nhibernate, Linq To SQL, Entity Framework)
Pavel Tsukanov
 
Павел Юрийчук - Разработка приложений под мобильные браузеры
Павел Юрийчук - Разработка приложений под мобильные браузерыПавел Юрийчук - Разработка приложений под мобильные браузеры
Павел Юрийчук - Разработка приложений под мобильные браузерыUA Mobile
 
Игры с виртуализацией в JavaScript, или как я переписал эмулятор, Евгений Пот...
Игры с виртуализацией в JavaScript, или как я переписал эмулятор, Евгений Пот...Игры с виртуализацией в JavaScript, или как я переписал эмулятор, Евгений Пот...
Игры с виртуализацией в JavaScript, или как я переписал эмулятор, Евгений Пот...
Ontico
 
Vladimir V Perepelitsa Ae Highload
Vladimir V  Perepelitsa Ae HighloadVladimir V  Perepelitsa Ae Highload
Vladimir V Perepelitsa Ae Highloadrit2010
 
Как мы разрабатываем новый фронтенд / Филипп Нехаев (Tinkoff.ru)
Как мы разрабатываем новый фронтенд / Филипп Нехаев (Tinkoff.ru)Как мы разрабатываем новый фронтенд / Филипп Нехаев (Tinkoff.ru)
Как мы разрабатываем новый фронтенд / Филипп Нехаев (Tinkoff.ru)
Ontico
 
Pconnect: граната в руках обезьяны (Сергей Аверин)
Pconnect: граната в руках обезьяны (Сергей Аверин)Pconnect: граната в руках обезьяны (Сергей Аверин)
Pconnect: граната в руках обезьяны (Сергей Аверин)Ontico
 
Pconnect: граната в руках обезьяны
Pconnect: граната в руках обезьяныPconnect: граната в руках обезьяны
Pconnect: граната в руках обезьяны
Sergey Xek
 
[jeeconf-2011] Java Platform Performance BoF
[jeeconf-2011] Java Platform Performance BoF[jeeconf-2011] Java Platform Performance BoF
[jeeconf-2011] Java Platform Performance BoFAleksey Shipilev
 
специализированные http-демона (Сергей Боченков, Александр Панков)
специализированные http-демона (Сергей Боченков, Александр Панков)специализированные http-демона (Сергей Боченков, Александр Панков)
специализированные http-демона (Сергей Боченков, Александр Панков)Ontico
 
Антон Щербаков, Отказоустойчивость на примере aviasales — почему даже если на...
Антон Щербаков, Отказоустойчивость на примере aviasales — почему даже если на...Антон Щербаков, Отказоустойчивость на примере aviasales — почему даже если на...
Антон Щербаков, Отказоустойчивость на примере aviasales — почему даже если на...
Tanya Denisyuk
 
Олег Царев, Кирилл Коринский Сравнительный анализ хранилищ данных
Олег Царев, Кирилл Коринский   Сравнительный анализ хранилищ данныхОлег Царев, Кирилл Коринский   Сравнительный анализ хранилищ данных
Олег Царев, Кирилл Коринский Сравнительный анализ хранилищ данныхSiel01
 
Подходы и технологии, используемые в разработке iOS-клиента Viber, Кирилл Лаш...
Подходы и технологии, используемые в разработке iOS-клиента Viber, Кирилл Лаш...Подходы и технологии, используемые в разработке iOS-клиента Viber, Кирилл Лаш...
Подходы и технологии, используемые в разработке iOS-клиента Viber, Кирилл Лаш...
Yandex
 

Similar to Баннерокрутилка на Erlang (20)

Continuous Deployment (in Russian)
Continuous Deployment  (in Russian)Continuous Deployment  (in Russian)
Continuous Deployment (in Russian)
 
Continuous deployment Smartling event
Continuous deployment Smartling eventContinuous deployment Smartling event
Continuous deployment Smartling event
 
Romanova techforum bash
Romanova techforum bashRomanova techforum bash
Romanova techforum bash
 
Async Python
Async PythonAsync Python
Async Python
 
Другая виртуализация
Другая виртуализацияДругая виртуализация
Другая виртуализация
 
Хорошо поддерживаемое в продакшне приложение / Николай Сивко (okmeter.io)
Хорошо поддерживаемое в продакшне приложение / Николай Сивко (okmeter.io)Хорошо поддерживаемое в продакшне приложение / Николай Сивко (okmeter.io)
Хорошо поддерживаемое в продакшне приложение / Николай Сивко (okmeter.io)
 
20111002 information retrieval raskovalov_lecture3
20111002 information retrieval raskovalov_lecture320111002 information retrieval raskovalov_lecture3
20111002 information retrieval raskovalov_lecture3
 
ORM технологии в .NET (Nhibernate, Linq To SQL, Entity Framework)
ORM технологии в .NET (Nhibernate, Linq To SQL, Entity Framework)ORM технологии в .NET (Nhibernate, Linq To SQL, Entity Framework)
ORM технологии в .NET (Nhibernate, Linq To SQL, Entity Framework)
 
Павел Юрийчук - Разработка приложений под мобильные браузеры
Павел Юрийчук - Разработка приложений под мобильные браузерыПавел Юрийчук - Разработка приложений под мобильные браузеры
Павел Юрийчук - Разработка приложений под мобильные браузеры
 
Игры с виртуализацией в JavaScript, или как я переписал эмулятор, Евгений Пот...
Игры с виртуализацией в JavaScript, или как я переписал эмулятор, Евгений Пот...Игры с виртуализацией в JavaScript, или как я переписал эмулятор, Евгений Пот...
Игры с виртуализацией в JavaScript, или как я переписал эмулятор, Евгений Пот...
 
Vladimir V Perepelitsa Ae Highload
Vladimir V  Perepelitsa Ae HighloadVladimir V  Perepelitsa Ae Highload
Vladimir V Perepelitsa Ae Highload
 
Как мы разрабатываем новый фронтенд / Филипп Нехаев (Tinkoff.ru)
Как мы разрабатываем новый фронтенд / Филипп Нехаев (Tinkoff.ru)Как мы разрабатываем новый фронтенд / Филипп Нехаев (Tinkoff.ru)
Как мы разрабатываем новый фронтенд / Филипп Нехаев (Tinkoff.ru)
 
Pconnect: граната в руках обезьяны (Сергей Аверин)
Pconnect: граната в руках обезьяны (Сергей Аверин)Pconnect: граната в руках обезьяны (Сергей Аверин)
Pconnect: граната в руках обезьяны (Сергей Аверин)
 
Pconnect: граната в руках обезьяны
Pconnect: граната в руках обезьяныPconnect: граната в руках обезьяны
Pconnect: граната в руках обезьяны
 
[jeeconf-2011] Java Platform Performance BoF
[jeeconf-2011] Java Platform Performance BoF[jeeconf-2011] Java Platform Performance BoF
[jeeconf-2011] Java Platform Performance BoF
 
специализированные http-демона (Сергей Боченков, Александр Панков)
специализированные http-демона (Сергей Боченков, Александр Панков)специализированные http-демона (Сергей Боченков, Александр Панков)
специализированные http-демона (Сергей Боченков, Александр Панков)
 
Антон Щербаков, Отказоустойчивость на примере aviasales — почему даже если на...
Антон Щербаков, Отказоустойчивость на примере aviasales — почему даже если на...Антон Щербаков, Отказоустойчивость на примере aviasales — почему даже если на...
Антон Щербаков, Отказоустойчивость на примере aviasales — почему даже если на...
 
JPHP
JPHPJPHP
JPHP
 
Олег Царев, Кирилл Коринский Сравнительный анализ хранилищ данных
Олег Царев, Кирилл Коринский   Сравнительный анализ хранилищ данныхОлег Царев, Кирилл Коринский   Сравнительный анализ хранилищ данных
Олег Царев, Кирилл Коринский Сравнительный анализ хранилищ данных
 
Подходы и технологии, используемые в разработке iOS-клиента Viber, Кирилл Лаш...
Подходы и технологии, используемые в разработке iOS-клиента Viber, Кирилл Лаш...Подходы и технологии, используемые в разработке iOS-клиента Viber, Кирилл Лаш...
Подходы и технологии, используемые в разработке iOS-клиента Viber, Кирилл Лаш...
 

Баннерокрутилка на Erlang

  • 2. Задача ● Выдача ссылок на новости ● База из тысяч новостей ● Ссылки выбираются произвольно ● Распределение – неравномерное ● Форматирование ссылок перед выдачей ● Ссылки должны иметь формат блока ● Дополнительные поля: идентификатор блока, …
  • 3. Ta-da! ● Требования: >= 5000 запросов в секунду ● Не справляемся – должны быстро выдавать пустую страницу, чтобы не «ломать» вёрстку ● Никакого кэширования ● Срок выполнения: полтора месяца. ● При этом у разработчика баннерокрутилки есть и другие задачи
  • 4. Структура решения ● Структуры в памяти, хранящие новости и статистику показов ● Множество потоков, обрабатывающих HTTP-запросы ● Контроллер ● добавляющий и удаляющий новости ● собирающий статистику ● на основе TCP-сокетов
  • 6. Erlang ● DSL для многопоточных приложений ● Встроенные в язык примитивы для посылки и приёма сообщений ● Встроенные в язык шаблоны поведения ● Встроенная в язык in-memory БД
  • 7. Структура решения ● Структуры в памяти, хранящие новости и статистику показов: mnesia/ets/dict! ● Множество потоков, обрабатывающих HTTP- запросы: gen_server! ● Контроллер: gen_tcp!
  • 8. Структура решения ● Структуры в памяти, хранящие новости и статистику показов: mnesia/ets/dict! ● Множество потоков, обрабатывающих HTTP- запросы: gen_server! ● который уже написан за нас! mochiweb/misultin ● Контроллер: gen_tcp! Batteries included
  • 10. Основная часть решения ● HTTP-сервер Mochiweb получает запрос, создаёт поток ● Поток забирает из Mnesia данные ● Поток производит выборку, сортирует данные, форматирует строки, выдаёт, умирает. Все счастливы. «In theory, there's no difference between theory and practice. In practice, there is». L. A. van der Snepscheut.
  • 11. Факап #1 У каждой новости есть коэффициент важности. В соответствии с этим коэффициентом необходимо выдавать новость чаще или реже остальных. ● Перед выдачей нужно назначать взвешенные произвольные числа каждой новости и делать по ним выборку. ● Новостей много.
  • 12. Факап #1 ● Mnesia построена на основе ETS ● http://www.erlang.org/doc/man/ets.html: «In the current implementation, every object insert and look-up operation results in a copy of the object.» ● Т. е. в копировании сотен новостей из потока в поток. Slow as hell.
  • 13. Эврика! ● Вместо ETS напишем собственную структуру данных на основе gen_server, dict, queue, blackjack и hookers. ● Повесим её в виде отдельного потока ● Будем делать там грубую предвыборку новостей, которые потом быстро скопируются в рабочий поток
  • 14. Результат: рост производительности в 3 раза ● Вывод: ● всегда думай, какие объёмы данных копируешь! ● профилируй!
  • 15. Основная часть решения v0.2 ● HTTP-сервер Mochiweb получает запрос, создаёт поток ● Поток отправляет запрос в gen_server ● gen_server производит предвыборку новостей и присылает результат ● Поток производит выборку, сортирует данные, форматирует строки, выдаёт, умирает. Все счастливы.
  • 16. Факап #2 Новости – это текст. Текст – это строки. ● Строки в Erlang – это связные списки символов ● IO в Erlang – это очень медленно
  • 17. Эврика! ● Если вы пишете на Erlang, то строка символов записывается так: "Hello world!~n" ● Конкатенация записывается так: "Hello " ++ Username ++ "!~n"
  • 18. Эврика! ● Если вы пишете на Erlang веб-приложения, то строка символов записывается так: <<"Hello world!~n">> ● Конкатенация записывается так: [<<"Hello ">>, Username, <<"!~n">>]
  • 19. Почему: ● <<>> – встроенный бинарный тип ● <<"">> – бинарная строка ● Списки символов нужно обрабатывать перед выдачей ● Вывод бинарных данных – это просто вызов writev(2) ● Blazingly Fast
  • 20. Почему: ● "Hello" ++ "!n" => "Hello!n" => строка ● Конкатенация списков – O(n) ● Вывод строки => цикл по списку из 7 символов ● [<<"Hello">>, <<"!n">>] – тип iolist(). ● Добавление в начало списка – O(1) ● Вывод => цикл по списку из 2 элементов ● Встроенным функциям I/O всё равно, что выводить
  • 21. Кроме того ● Строковые операции, наподобие обработки регулярных выражений, всё равно дорогие ● Впрочем, они вообще не очень дешевы. Обработку данных нужно делать не на этапе выдачи, а на этапе помещения в базу – до тех пор, пока позволяют объёмы памяти и специфика решаемой задачи. ● В данном случае кэширование конструируемых URL новостей и т. п. позволило отыграть 15%
  • 22. Результат: рост производительности в 10 (десять) раз ● Вывод: ● всегда думай, как обрабатывать строки! ● профилируй!
  • 23. Основная часть решения v0.3 ● HTTP-сервер Mochiweb получает запрос, создаёт поток ● Поток отправляет запрос в gen_server ● gen_server производит предвыборку новостей и присылает результат ● Поток производит выборку, сортирует данные, форматирует iolist()'ы, выдаёт, умирает.
  • 25. Основная часть решения v0.4 ● HTTP-сервер Misultin получает запрос, создаёт поток ● Поток отправляет запрос в gen_server ● gen_server производит предвыборку новостей и присылает результат ● Поток производит выборку, сортирует данные, форматирует iolist()'ы, выдаёт, умирает.
  • 26. Misultin ● Реализация gen_server, как и Mochiweb ● Интерфейс, абсолютно аналогичный Mochiweb ● Стабильно на 10-15% быстрее
  • 27. Результат ● Один человекомесяц ● Быстрое веб-приложение # ab -qc 7200 -n 450000 http://localhost/block/35237 | grep Requests per sec Requests per second: 7693.35 [#/sec] (mean) #
  • 28. Killing feature! Начиная со второй недели разработки (как только был написан каркас), приложение было готово к работе. В любой момент не работал только тот функционал, который не был дописан. ● Ни отладки ● Ни непредусмотренного поведения ● Только профилирование
  • 29. Killing feature! ● Ни отладки ● Ни непредусмотренного поведения В Erlang есть концепция «Let it crash». Близкий перевод – «Ну и хрен с ним».
  • 30. Let it crash ● На обычном языке программирования: res = web_server.start_link(callback = Fun) if res == web_server.port_in_use: raise Exception("Port in use") elif res == web_server.socket_error: raise Exception("Socket error") elif res == errno.EACCES: raise Exception("Not enough privileges")
  • 31. Let it crash ● На Erlang: {ok, Pid} = misultin:start_link([{loop, Fun}]).
  • 32. Let it crash ● На Erlang: {ok, Pid} = misultin:start_link([{loop, Fun}]). ● Если что-то шандарахнется, то предположение misultin:start_link/1 => {ok, _} окажется неверным, и поток вылетит сам с сообщением, например, таким: {badmatch, {error, eacces}}
  • 33. Результат ● Один человекомесяц ● Быстрое веб-приложение ● Стабильное веб-приложение – за счёт eunit и «Let it crash» ● Минимум кода – за счёт множества встроенных примитивов и «Let it crash» ● Минимум требуемого опыта – Erlang изучается за 2 недели
  • 34. Уровень программиста ● С одной стороны, Erlang учится за 2 недели ● С другой стороны, нужно иметь навыки программирования. Not all batteries included Для написания баннерокрутилки в разное время требовался то JSON-декодер, то перекодировка из UTF8 в CP1251, то htmlspecialchars(). Ничего этого в stdlib нет, нужно брать сторонние библиотеки, оценивать их работоспособность и производительность.
  • 35. Напутствие ● Предобрабатывай данные, пока это дёшево! ● Не выполняй одни и те же операции дважды! ● Используй «Let it crash» в интерфейсах собственного кода! ● Профилируй! ● Переписывай медленные операции на C, PHP, OCaml, whatever: существуют открытые биндинги