Showing posts with label yaws. Show all posts
Showing posts with label yaws. Show all posts

Sunday, January 25, 2009

Yaws и потребление памяти

Уважаемые телерадиослушатели, мегаблог не совсем умер :)

В комментариях к записи про Yaws жжюзер [info]alekciy поинтересовался, сколько yaws будет хавать памяти на одно HTTP соединение. Понятно, что немного, но конкретные циферки всегда красноречивее слов. Не вопрос — на коленке собрался небольшой test suite. По хорошему тут надо было бы взять нормальный стенд — сервер и пяток клиентов (давняя мечта, повторить тот самый тест самому, так как его справедливо критикуют за отсутствие подробного описания условий тестирования), но под рукой только рабочий нотебук с убунтой 8.04 (Celeron 1.7, 2G памяти).

Итак, берем yaws 1.79, в качестве генератора траффика программка на C, за основу взял пример работы с epoll какого-то японца.

Тупо создаем соединения к серверу, запрашиваем файл и мееедленно (по байту) читаем ответ.

$ uname –a 
Linux lrrr-laptop 2.6.24-23-generic #1 SMP Thu Nov 27 18:44:42 UTC 2008 i686 GNU/Linux 

Исходники клиента.

График:

 yaws-mem

По оси X — количество одновременных соединений, по Y resident size процесса в килобайтах. Понятно, тут хватило б и двух точек, но мало ли что, вдруг, например, gc стал бы захлебываться с какого-то момента, надо было удостовериться.

После 10000 соединений у меня yaws начинает их дропать, хотя наверняка можно это как-то победить, в связи с убогостью тестовых условий я решил не заморачиваться.

Итого, если поделить — отжирается 14 кб памяти на коннект. Неплохо. Yaws (ожидаемо) не кушал CPU (показатель болтался около 1-2%), но, почему-то, довольно медленно принимал соединения — удавалось создать порядка 10 коннектов в секунду.

Попытка поставить в те же условия nginx пока не увенчалась успехом, соединения создаются раз в десять быстрее, но в районе 700 коннектов nginx сначала отдает 500 ошибку, потом молча закрывает соединения, а потом начинает приходить ECONNRESET. Думаю, он это делает из лучших побуждений, но я пока не нашел как на это повлиять.


Saturday, February 09, 2008

Yaws — веб-сервер на Erlang

В самом начале обещал рассказать про веб-приложения на эрланге. Наверное, пора сворачивать ближе к теме.

В качестве веб-сервера для Erlang-приложений лучшим вариантом является написанный на эрланге же веб-сервер Yaws. Чем он хорош — он довольно сильно заточен под высо­копро­изво­ди­тельные приложения, и динамические страницы там удобно генерировать на эрланге.

Сначала насчет производительности:

Картинка известная, подробнее узнать, как она получена можно тут.  По горизонтали это количество параллельных запросов  к серверу (очень медленных клиентов), по вертикали — сколько кб/с при этом параллельно может отдавать сервер одному быстрому клиенту. Красненькое это yaws, синенькое и зелененькое это Apache, который после нескольких тысяч тихо умирает.

Конечно, Apache сравнивать с yaws не очень честно — все-таки апач продукт сложный и намного более многофункциональный, с кучей дополнительных модулей и настроек, и, в общем-то использовать его для отдачи статических страниц не очень принято. Однако ж картинка все-таки очень показательна, возможность держать много параллельных соединений важна в любом случае, да и с динамикой дела у yaws должны быть тоже хорошо (см. например Erlang vs PHP на Computer Language Shootout).

Пару слов об установке Yaws — с линуксом проблем, конечно, нет, на винду поставить тоже можно из-под Суgwin, но чтобы избежать лишней головной боли, обратите внимание, чтобы в пути к эрлангу и директории home не было пробелов (а последняя по умолчанию в "Documents And Settings" находится). Еще пара полезных замечаний про процесс установки есть тут.

 

Настраивается yaws с помощью конфиг-файла, там все довольно тривиально — дефолтный файл можно пока особенно не менять, разве что установить root директорию (параметр docroot).

Простейшее приложение с использованием yaws:

<head><title>Hello world using Yaws</title></head>
<body>
<erl>
out(A) ->
   case queryvar(A, "name") of
      {ok, Name} ->
        {html, "<div style=\"font-size: 12pt;\"> Hello, " ++ Name ++"</div>"};

      undefined ->
        {html, "<b> Name parameter required </b>"}
    end.
</erl>
</body>

 

Сохраняем его как hello.yaws в root директории.

hello-yaws

.yaws файл, как уже видно, это просто HTML шаблон. Каждый блок между тегами <erl> и </erl> компилируется в отдельный Erlang модуль. Каждый такой блок должен содержать функцию out/1, которой в качестве параметра передается структура, содержащая параметры запроса. Есть много вариантов как можно возвращать ответ, наиболее интересны два:

использованный выше

{html, HtmlString}

Где HtmlString — просто кусок HTML в виде строки, как в примере выше.

И чуть более удобный

{ehtml, Term}

Где Term — тот же HTML в виде терма Erlang, где тэги представляются кортежами или списками кортежей. Например, вот такой терм

{p, [],
    [
        {b, [], "Hello World"},
        {a, [{href, "http://www.example.com"}], 
           "link"}
    ]
}

преобразуется сервером в HTML-строку

<p>
  <b>Hello World</b>
  <a href="http://example.com">link</a>
</p>

Выглядит немного жутковато, но быстро привыкаешь и работать с кортежами становится намного удобнее чем со строками.

Еще Yaws, кроме того что является просто веб-сервером, предоставляет немало дополнительных инструментов, таких как автоматическая поддержка сессий, cookie, механизмов удаленного вызова процедур на основе SOAP и JSON-RPC.

Для полноценного фреймворка — аналога Ruby on Rails и прочих, API Yaws, конечно, не дотягивает (для этого есть библиотека ErlyWeb), но для небольших приложений этого должно быть вполне достаточно.