Выступление Андрея Сумина, mail.ru group, на high performance conference
DESCRIPTION
Выступление Андрея Сумина, Руководителя разработки фронт-энда, Mail.Ru Group: "JavaScript на сервере, 1ms на трансформацию" на #HPC 9 августа, 2012.TRANSCRIPT
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
Данные на февраль 2012 года
Размер HTML, который генерирует v8 65кб.
Время, работы v8 на запрос 1ms.
В среднем v8 требует 40MB на контекст.
Пол года спустя
Ни одной утечки памяти
Ни одного падения v8
Touch главная
Touch почта
Проблемы v8
http://sysoev.ru/prog/v8.html
Полезные ссылки
— http://code.google.com/p/v8/— https://github.com/mailru/fest— http://sysoev.ru/prog/v8.html
Андрей Сумин, [email protected]
Возможности 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:choose
try{ 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>";