Язык Lua — секреты производительности / Ник Заварицкий...
-
Upload
ontico -
Category
Engineering
-
view
361 -
download
3
Transcript of Язык Lua — секреты производительности / Ник Заварицкий...
Lua:секреты производительностиNICK ZAVARITSKY [email protected]
О докладчике• занимаюсь Tarantool
• это СУБД
• вместо языка запросов — Lua
• сейчас работаем над SQL
• in-memory DB ⇒ SQL JIT
JIT в Lua• по скорости не уступает V8 / HHVM / …
• надо уметь готовить
• LUAJIT: 78 KSLOC
• V8: 2100 KSLOC
Доступные JIT-технологии
• кодогенерация в язык с JIT
• LLVM
• наш опыт: JIT в production за 6 месяцев
Perl-5.22.1
Python-2.7.11
Ruby-2.2.5
Java (openjdk-1.8 -Xint)
JavaScriptCore-1.12.3 (LLint)
LuaJit-2.1.0-beta2 (-j off)
PHP-7.1.0-dev
Java (openjdk-1.8)
PyPy-4.0.1
SpiderMonrey-1.8.5
V8-3.14.5.10
JavaScriptCore-1.12.3
LuaJit-2.1.0-beta2
PHP/llvm-jit
GCC-5.3 -O31 100 10000
1111
131416
2730
469298
190243
609940
2 063
local p = { "Hello, world!", "", RIPJSB = 1750, [":)"] = 1963 }
print(p[0]) -- nil print(p[1]) -- Hello, world! print(p.RIPJSB) -- 1750 print(p["RIPJSB"]) -- 1750
-- closures function uniqueid (prefix) local counter = 0 return function () counter = counter + 1 return (prefix or "_")..counter end end
local u = uniqueid("awesome") print(u()) -- awesome1 print(u()) -- awesome2
ffi.cdef [[ struct Complex { double real; double imag; }; ]] local vec = ffi.new("struct Complex[?]", 1000) vec[0].real = 42.0
ffi.cdef [[ int getpid(); int kill(int pid, int sig); ]] ffi.C.kill(ffi.C.getpid(), 9) -- Ouch!
function clamp(x) return math.max(x, 0) end
GGET 1 0 ; "math" TGETS 1 1 1 ; "max" MOV 2 0 KSHORT 3 0 CALLT 1 3
0:
1:
2:
3:
param_x
_G["math"]["max"]
param_x
0
0:
1:
2:
3:
param_x
_G["math"]["max"]
param_x
0
/* {foo = "bar"} */ lua_newtable(L); lua_pushstring(L, "foo"); lua_pushstring(L, "bar"); lua_settable(L, -2);
LUAJIT: компилятор
Perl-5.22.1
LuaJit-2.1.0-beta2 (-j off)
LuaJit-2.1.0-beta2
GCC-5.3 -O3
1 100 10000
11
13
98
2 063
JIT-компилятор• профилирует код на лету
• находит хотспоты
• компилирует горячий код
• холодный код не компилирует
• full-method vs. tracing JIT
Что такое “трасса”?• последовательность байткодов в порядке выполнения
• видны типы переменных
• посещаем одну ветку в if-then-else
• линейная — легко оптимизировать
• если потом типы изменятся?
• если нужна другая ветка в if? — guard
Откуда берутся трассы?• нагретая инcтрукция FORI/LOOP/FUNC* включает запись трассы
• когда останавливать запись?
• FORI/LOOP/FUNC* заменяем на JFORI/JLOOP/JFUNC*
• возврат в интерпретатор — по выходу из функции или по guard
Side-трассы
• для guard-ов собирается статистика
• из горячего guard вырастает дочерняя трасса
• JFORI/JLOOP/JFUNC* во время записи?
Где спотыкается JIT• NYI
• сложные ветвления
• равновероятные ветвления в цикле
• циклы с малым числом итераций
• нестабильные типы
• LuaC
Как лечить?
$ luajit -jdump=tx test.lua ---- TRACE 1 start test.lua:1 ---- TRACE 1 abort test.lua:2 -- NYI: FastFunc print
Takeaway #1• Lua — современный и высокоуровневый
• легко встраивается
• работает быстро
• any sufficiently complicated C program contains …
an implementation of half of Common Lisp —Greenspun’s 10th rule
Takeaway #2• LUAJIT: 78 KSLOC / 0.013 секунд на тесте CLBG/M
• V8: 2100 KSLOC / 0.016 секунд
• трассирующий JIT проще в реализации
• у программиста больше забот
• Emscripten для LUAJIT?
Takeaway #3
• LUAJIT легко похачить
• идеальный объект для изучения*
sql("SELECT * FROM orders WHERE id = %", id)
Схемы Avro{ "First": "John", "Last": "Doe" }
{ "name": "Person", "type": "record", "fields": [
{ "name": "First", "type": "string" },
{ "name": "Last", "type": "string" }
] }
Хранится как: ["John", "Doe"]
[ "John", "Doe", "Was here!" ]
{ "First": "John", "Last": "Doe" "Notes": "Was here!" }
v2 v2
Avro: версионирование
SAX-подобный формат
ARRAY(3) John Doe Was here
{ "First": "John", "Last": "Doe" "Notes": "Was here!" }
["John", "Doe", "Was here!"]
DICT(3) First John Last Doe Notes Was here
ARRAY(3) John Doe Was here
DICT(3) First John Last Doe Notes Was here
CHECK in[0].type == ARRAY CHECK in[0].length == 3 CHECK in[1].type == STRING CHECK in[2].type == STRING CHECK in[3].type == STRING
out[0].type = DICT out[1].length = 3 out[2] = "First" out[3] = in[1] out[4] = "Last" out[5] = in[2] out[6] = "Notes" out[7] = in[3]
RPS (×1000)
500
1000
1500
2000
2500
3000
3500
Baseline (C) Codegen (LuaJIT) Codegen (LLVM)
v1v2
v3 v4
v5
Final Takeaway• any sufficiently complicated C program contains …
an implementation of half of Common Lisp — Greenspun’s 10th rule
• Lua — современный и высокоуровневый
• работает быстро, легко встраивается
Ссылки• http://luajit.org/list.html
• Vyacheslav Egorov: What I learned from LUAJIT https://youtu.be/EaLboOUG9VQ
• terralang.org
• Андрей Дроздов: Хранение json-документов в Tarantool
• Дмитрий Стогов: Развитие ветки PHP-7 https://youtu.be/WIcdjJbFuCs
HighLoad, 8 окт. 18:00
HighLoad, 8 окт. 12:00