85
Optimizing Lua Applications for LuaJIT and OpenResty [email protected]Yichun Zhang (@agentzh) 2016.9

Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "", SNI name ... 4096 bytes GC total

Embed Size (px)

Citation preview

Page 1: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

 Optimizing Lua Applications for

LuaJIT and OpenResty 

[email protected]☺Yichun Zhang (@agentzh)

 

 2016.9

 

Page 2: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total
Page 3: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

♡ NGINX + LuaJIT

Page 4: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total
Page 5: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total
Page 6: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total
Page 7: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

☺ Flame Graphs

Page 8: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total
Page 9: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total
Page 10: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total
Page 11: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

☺ I/O

Page 12: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

♡ Off-CPU Flame Graphs

Page 13: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total
Page 14: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

    # assuming the nginx worker process to be analyzed is 10901.   ./sample­bt­off­cpu ­p 10901 ­t 5 > a.bt 

Page 15: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

    # using Brendan Gregg's flame graph tools:   $ stackcollapse­stap.pl a.bt > a.cbt   $ flamegraph.pl a.cbt > a.svg 

Page 16: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total
Page 17: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

♡ Synchronously nonblocking I/O

Page 18: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

♡ Light threads & semaphores

Page 19: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

    local thread_A, err =           ngx.thread.spawn(func1)    ­­ thread_A keeps running asynchronously   ­­ in the background of the current   ­­ "light thread". 

Page 20: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

    local ok, res1, res2 =               ngx.thread.wait(thread_A, thread_B) 

Page 21: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total
Page 22: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

    local ok, err = ngx.thread.kill(thread_A) 

Page 23: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

♡ Full-Duplex Cosockets

Page 24: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

    local sock = ngx.socket.tcp()   local ok, err = sock:connect("www.cloudflare.com",                                443)    ok, err = sock:sslhandshake(       false,  ­­ disable SSL session       "www.cloudflare.com",  ­­ SNI name       true  ­­ verify everything   ) 

Page 25: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

♡ Timers and Sleeps

Page 26: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

    ­­ create a timer triggered after 1 sec   ngx.timer.at(1000, function (premature)                           do_something()                      end)    ­­ sleeps for 1 sec then continue   ngx.sleep(1000) 

Page 27: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

☺ CPU

Page 28: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

♡ on-CPU Flame Graphs

Page 29: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total
Page 30: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total
Page 31: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total
Page 32: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

♡ Lua-land Flame Graphs

Page 33: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total
Page 34: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

http://agentzh.org/misc/flamegraph/lua-on-cpu-local-waf-jitted-only.svg

Page 35: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

    lj­lua­stacks.sxx ­­arg time=5 \                     ­­skip­badvars \                     ­x 6949 \                     > a.bt 

Page 36: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

♡ LuaJIT Built-in Profilervs

SystemTap Sampling

Page 37: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

♡ Dynamic Allocations & Garbage Collection

Page 38: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

Lua tables

Page 39: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

    lj_tab_new    lj_tab_resize    lj_tab_len 

Page 40: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

   table.new(10, 20)

Page 41: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

   table.clear(tb)

Page 42: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

   tb[key1] = val1   tb[key1] = nil   tb[key2] = val2

Page 43: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

Lua strings

Page 44: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

   ?   s = s .. r

Page 45: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

   ­­ tb[#tb + 1] is slow!   idx = idx + 1   tb[idx] = r    s = table.concat(tb) 

Page 46: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

   ?   string.sub(s, i, i)

Page 47: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

   string.byte(s, i, i)

Page 48: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

Lua functions

Page 49: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

   foo = function (...)       ...   end

Page 50: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total
Page 51: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

♡ JITting vs Interpreting

Page 52: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

lua-resty-core

Page 53: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total
Page 54: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total
Page 55: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total
Page 56: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

    jit.v    jit.dump 

Page 57: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

    lj­lua­stacks.sxx ­­arg nojit=1 ...    lj­lua­stacks.sxx ­­arg nointerp=1 ... 

Page 58: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

♡ Biased vs UnbiasedBranching

Page 59: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

♡ Lua code generation atop LuaJIT 

JIT over a JIT!

Page 60: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

♡ Regexes

Page 61: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

    /     \d+ \. \d+   | \. \d+   | \d+   /x 

Page 62: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total
Page 63: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

sregex

Page 64: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total
Page 65: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total
Page 66: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total
Page 67: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total
Page 68: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total
Page 69: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total
Page 70: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

☺ Memory

Page 71: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

♡ Memory-Leak Flame Graphs

Page 72: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total
Page 73: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

♡ GC Object Analaysis

Page 74: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

 

 

   $ lj­gc­objs.sxx ­x 14378 ­D MAXACTION=200000

   Start tracing 14378 (/opt/nginx/sbin/nginx)

 

   main machine code area size: 65536 bytes

   C callback machine code size: 4096 bytes

   GC total size: 9683407 bytes

   GC state: pause

 

   27948 table objects: max=131112, avg=106, min=32, sum=2983944 (in bytes)

   22343 string objects: max=1421562, avg=198, min=18, sum=4432482 (in bytes)

   12168 userdata objects: max=8916, avg=50, min=27, sum=619223 (in bytes)

   2837 function objects: max=148, avg=27, min=20, sum=78264 (in bytes)

   1200 upvalue objects: max=24, avg=24, min=24, sum=28800 (in bytes)

   650 proto objects: max=3860, avg=313, min=74, sum=203902 (in bytes)

   349 thread objects: max=1648, avg=774, min=424, sum=270464 (in bytes)

   202 trace objects: max=1560, avg=375, min=160, sum=75832 (in bytes)

   9 cdata objects: max=36, avg=17, min=12, sum=156 (in bytes)

   JIT state size: 7696 bytes

   global state tmpbuf size: 710772 bytes

   C type state size: 4568 bytes

 

   My GC walker detected for total 9683407 bytes.

   45008 microseconds elapsed in the probe handler.

 

 

Page 75: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

    (gdb) lgcstat   15172 str        objects: max=2956, avg = 51, min=18, sum=779126    987 upval      objects: max=24, avg = 24, min=24, sum=23688    104 thread     objects: max=1648, avg = 1622, min=528, sum=168784    431 proto      objects: max=226274, avg = 2234, min=78, sum=963196    952 func       objects: max=144, avg = 30, min=20, sum=28900    446 trace      objects: max=23400, avg = 1857, min=160, sum=828604   2965 cdata      objects: max=4112, avg = 17, min=12, sum=51576   18961 tab        objects: max=24608, avg = 207, min=32, sum=3943256      9 udata      objects: max=176095, avg = 39313, min=32, sum=353822 

Page 76: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

♡ Streaming Processing

Page 77: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total
Page 78: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total
Page 79: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

♡ Streaming Regex (sregex)

Page 80: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

♡ The cost of abstractions

Page 81: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

♡ The oppportunities ofnew abstractions

Page 82: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

♡ Business-Level Domain Specific Languages

Page 83: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

ModSecurity's syntax sucks.

Page 84: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total

☺  Any questions? ☺

Page 85: Optimizing Lua Applications for LuaJIT and OpenResty · Optimizing Lua Applications for LuaJIT and OpenResty ... "",  SNI name ... 4096 bytes GC total