JavaScript на сервере, 1ms на трансформацию (Андрей Сумин)

Preview:

Citation preview

JavaScript на сервере,1ms на трансформацию

Андрей Сумин, Mail.ru

Зачем?

Зачем?— Пишут одни, а используют другие

Зачем?— Пишут одни а используют другие— JavaScript специалисты

Зачем?— Пишут одни а используют другие— JavaScript специалисты— Шаблонизация на клиенте

Что нужно

XSLT JS

XSLT JS

XSLT/head.xml

<title><fest:get name="title"/></title><fest:set name="title">Mail.ru</fest:set>

XSLT/head.xml

<title><fest:get name="title"/></title><fest:set name="title">Mail.ru</fest:set>

/mail.xml<fest:include src="head.xml"/><fest:set name="title">Почта</fest:set>

JavaScript<fest:script>

var text = "mail.ru"</fest:script><fest:value>text</fest:value>

JavaScript<fest:script>

var text = "mail.ru"</fest:script><fest:value>text</fest:value>

mail.ru

XML

XML— IDE

XML— IDE— Валидация из коробки

XML— IDE— Валидация из коробки— Name spaces

XML— IDE— Валидация из коробки— Name spaces— SAX, XSLT, XSD, DTD …

XML— IDE— Валидация из коробки— Name spaces— SAX, XSLT, XSD, DTD ...— XML to XML

Реализация

Ковбойство

Структураvs

Функция

Структура vs функция[ {action:"template"},

"<html>...",{action:"value"},"json.value"]

Структура vs функция[ {action:"template"},

"<html>....”,{action:"if"},"json.value","<span>true</span>","<span>false</span>"]

Структура vs функцияfunction template(json){

var html = "";html += "<html>…";html += json.value;return html;

}

Структура vs функция

200ms

3ms

Структура vs функцияfest:forearch for(i = 0; i < l; i++) {}fest:if if(value) {}fest:choose if(value) {} else {}

fest:set set[name] = functionset[name] = function

Структура vs функция<span> html += "<span>"; mail.ru html += "mail.ru";</span> html += "</span>";

Структура vs функция<span> html += "<span>"; mail.ru html += "mail.ru";</span> html += "</span>";

html += "<span>mail.ru</span>";

30%

Безопасность

try catch

try catchescape

Безопасность<fest:value>json.name</fest:value>try {

html += escape(json.name);} catch(e) {

log(e.message);}

Интеграция

Интеграция— С— Perl— Python— NodeJS

Интеграция— С fest_log— Perl fest_file— Python fest_dirname— NodeJS

Интеграция— С fest_log— Perl fest_file— Python fest_dirname— NodeJS

— Браузер

Реальные пользователи

4ms

Реальные пользователиmsg_length = 5msg_1_title = "letter"msg_1_Unread = 1

Реальные пользователиmsg_length = 5msg_1_title = "letter"msg_1_Unread = 1

msg = [ {title: "letter", Unread: true} ]

Реальные пользователиhash -> v8 api -> JavaScripthash -> string -> JSON.parse -> JavaScripthash -> string -> compile -> Javascript

Реальные пользователиLocal<String> script = String::new(

"template(\"{value:'mail.ru'}\")");Local<Script> cs = Script::Compile( script );Local<Value> result = cs->Run();

2 + 4 = 6ms

67%

NodeJS

NodeJS 4ms

Реальные пользователиmsg_length = 5msg_1_title = "letter"msg_1_Unread = 1

Реальные пользователиmsg_length = 5msg_1_title = "letter"msg_1_Unread = 1

get('msg_' + i + '_title')

3ms

Реальные пользователи30 часов одно ядро 2.2 ГГц Xeon10 000 000+ хитов1.6ms среднее время трансформации992 422 10% между 2 и 5ms208 464 2% между 5 и 10ms396 49 0,4% больше 10ms

Продакшен, главная

50% x3

65+100=165кб

RB lite v8 lite

Почти продакшенhtml += "foo";html += rb(id);html += "bar";

Почти продакшенhtml += "foo"; push_string("foo");html += rb(id); push_rb(id);html += "bar"; push_string("bar");

50% x2

440 000 000

440 000 000110 000 000

Данные на сегодняРазмер HTML, который генерирует v8 65кб.

Время, работы v8 на запрос 1ms.

В среднем v8 требует 40MB на контекст.

Проблемы v8

http://sysoev.ru/prog/v8.html

Полезные ссылки— http://code.google.com/p/v8/— https://github.com/mailru/fest— http://sysoev.ru/prog/v8.html

Андрей Сумин, andrewsumin@corp.mail.ru

Возможности fest

fest:value<fest:value>json.name</fest:value>try {

html += escape(json.name);} catch(e) {

log(e.message);}

fest:value<fest:value output="text">json.name</fest:value>try {

html += json.name;} catch(e) {

log(e.message);}

fest:value<fest:value safe="true">json.name</fest:value>

html += json.name;

fest:if<fest:if test="json.condition">…</fest:if>

try{ condition = json.condition } catch(e) { log(e) }

If (condition){ … }

fest:choose<fest:choose>

<fest:when test="json.condition">…</fest:when><fest:when test="false">…</fest:when><fest:otherwise>…</fest:otherwise>

</fest:choose>

fest:choosetry{ condition = json.condition } catch(e) { log(e) }If (condition){…}else{

try{ condition = false } catch(e) { log(e) }if (condition){}else {} }

fest:foreach<fest:foreach iterate="list" index="i"></fest:foreach>var i;try{ foreach = list } catch(e) { foreach=[]; log(e) }var l = list.length;for(i = 0; i < l ; i++) { … }

fest:for<fest:for iterate="hash" index="i"></fest:for>var i;try{ for = hash } catch(e) { for={}; log(e) }for(i in for) { … }

fest:space<fest:space/>

html += " ";

fest:script<fest:script> … </fest:script>

try{ … } catch (e) { log(e) }

fest:insert<script>

<fest:insert src="script.js"/></script>

html += "<script>…</script>";

Recommended