From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from [87.239.111.99] (localhost [127.0.0.1]) by dev.tarantool.org (Postfix) with ESMTP id 5ED5A6EC58; Sun, 1 Aug 2021 15:57:57 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 5ED5A6EC58 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1627822677; bh=4ah2AzIndGduTJLHgnkPypqPztqtly97/iPotKZ9Cl0=; h=Date:To:Cc:References:In-Reply-To:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=Rz6+FtT6K32lTA/WAVfRm2hp00J6Cpwa2puW+zUwcASnlndKH/BSuyyS63g2r2Rn9 +A/Yj2ZE2q2uuKfOUmvxdduVPKaBjtuR/uZJPyii88BrdqVnVeFovVPn4B/YTrjCQP rOd17JxAbalevRBc/Hxg3imV4PBny6nlsuyxHRAE= Received: from smtpng2.i.mail.ru (smtpng2.i.mail.ru [94.100.179.3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id E9D296EC58 for ; Sun, 1 Aug 2021 15:57:55 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org E9D296EC58 Received: by smtpng2.m.smailru.net with esmtpa (envelope-from ) id 1mAB2Q-0004hB-Ec; Sun, 01 Aug 2021 15:57:55 +0300 Date: Sun, 1 Aug 2021 15:34:17 +0300 To: Sergey Kaplun Cc: Vladislav Shpilevoy , tarantool-patches@dev.tarantool.org Message-ID: <20210801123417.GA27855@tarantool.org> References: <20210618181416.25454-1-skaplun@tarantool.org> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline In-Reply-To: <20210618181416.25454-1-skaplun@tarantool.org> X-Clacks-Overhead: GNU Terry Pratchett User-Agent: Mutt/1.10.1 (2018-07-13) X-4EC0790: 10 X-7564579A: B8F34718100C35BD X-77F55803: 4F1203BC0FB41BD941C43E597735A9C354866C15C72ED952BE56FFA0EFAF5B8C182A05F5380850405732AFAB5B7328F1BE307012AEB01115483867081C4604888FCE3EA7E200D1F7 X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE7AEA4A6B3AFC9B957C2099A533E45F2D0395957E7521B51C2CFCAF695D4D8E9FCEA1F7E6F0F101C6778DA827A17800CE7AF18881564A951B9EA1F7E6F0F101C6723150C8DA25C47586E58E00D9D99D84E1BDDB23E98D2D38BBCA57AF85F7723F27027840C41979973CC8A062AA43EA2CCCC7F00164DA146DAFE8445B8C89999728AA50765F7900637F6B57BC7E64490618DEB871D839B7333395957E7521B51C2DFABB839C843B9C08941B15DA834481F8AA50765F7900637F6B57BC7E6449061A352F6E88A58FB86F5D81C698A659EA7E827F84554CEF5019E625A9149C048EE9ECD01F8117BC8BEE2021AF6380DFAD18AA50765F790063735872C767BF85DA227C277FBC8AE2E8BC6A536F79815AD9275ECD9A6C639B01B4E70A05D1297E1BBCB5012B2E24CD356 X-C1DE0DAB: 0D63561A33F958A5E3AA54F12F6DE70572AEC2A84AC7C4E3818B9A94ACC168BDD59269BC5F550898D99A6476B3ADF6B47008B74DF8BB9EF7333BD3B22AA88B938A852937E12ACA751B940EDA0DFB0535410CA545F18667F91A7EA1CDA0B5A7A0 X-C8649E89: 4E36BF7865823D7055A7F0CF078B5EC49A30900B95165D34505665BFD4C70705222DA6A1923D2ACA6800F0939B914428281D79A18B81AC29710362044B0732E21D7E09C32AA3244C1347FA5EC8F12813D15C5231F579BBF2A8CE788DE6831205927AC6DF5659F194 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2biojMCfuYI4PredbFtcDmNH4uA== X-Mailru-Sender: 689FA8AB762F7393C37E3C1AEC41BA5D6EDE101145E454F6AD936A4EDBF522DFA7C8D0F45F857DBFE9F1EFEE2F478337FB559BB5D741EB964C8C2C849690F8E70A04DAD6CC59E33667EA787935ED9F1B X-Mras: Ok Subject: Re: [Tarantool-patches] [PATCH] lua: refactor port_lua_do_dump and encode_lua_call X-BeenThere: tarantool-patches@dev.tarantool.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Igor Munkin via Tarantool-patches Reply-To: Igor Munkin Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" Sergey, Thanks for the patch! The changes are fine, but please consider the comments below. On 18.06.21, Sergey Kaplun wrote: > The old code flow was the following: > 1) `struct port_lua` given to `port_lua_do_dump()` has Lua stack with > arguments to encode to MessagePack > 2) The main coroutine `tarantool_L` is used with `lua_cpcall()` to call > `encode_lua_call_16()` or `encode_lua_call()` > 3) Objects on minor coroutine are encoded via `luamp_encode_call16()` or What is this minor coroutine? To make terms more consistent in scope of this commit message, let's define this in the first bullet and use it everywhere. For me the best option is "port coroutine". > `luamp_encode()`. This encoding may raise an error on unprotected The next bullet is recommended to be started from this sentence. > `port->L` coroutine. This coroutine has no protected frame on it > and this call should fail in pure Lua. It is forbidden to call Ditto. > anything on unprotected coroutine [1] (Lua 5.1 sets protection only > for specific lua_State [2] and calls a panic function if we raise an > error on unprotected lua_State [3]). Netherless, there is no panic Ditto. > at now due to two facts. The first one is LuaJIT's support of C++ And sublist is strongly recommended for "the first" and "the second" facts. It'll make this War and Peace part more readable. > exception handling [4] that allows to raise an error in Lua and > catch it in C++ or vice versa. But documentation still doesn't > permit errors on unprotected coroutines (at least we must set > try-catch block). The second one is double monkey-patching of LuaJIT I doubt this is monkey-patching, but rather a monkey's patch. > to restore currently executed coroutine, when C function or fast > function raises an error [5][6] (see related issue here [7][8]). > For these reasons, when an error occurs, the unwinder searches and > finds the C-protected stack frame from the `lua_cpcall()` for the > `tarantool_L` coroutine and unwinds until that point (without > aforementioned patches LuaJIT just calls a panic function and exit). > 4) If an error is raised, and `lua_cpcall()` returns not `LUA_OK`, then > the error from `port->L` coroutine is converted into a Tarantool error > and a diagnostic is set. > > The auxiliary usage of `tarantool_L` coroutine is redundant and doesn't Well, as for me, the main problem is violating Lua coroutine practice (it's worth to mention, that internal unwinder used on M1 is not such flexible, so this misuse still leads to panic call), and the minor reason is tarantool_L usage redundancy. > respect Lua idiomatic of usage. So this patch drops it and uses only > minor coroutine instead with `lua_pcall()`. > > Functions to encode are saved as entrance in the `LUA_REGISTRY` table > to reduce GC pressure, like it is done for other handlers [9]. > > [1]: https://www.lua.org/manual/5.2/manual.html#4.6 > > If an error happens outside any protected environment, Lua calls a > > panic function Some copy-pasting artefacts. > [2]: https://www.lua.org/source/5.1/lstate.h.html#lua_State > [3]: https://www.lua.org/source/5.1/ldo.c.html#luaD_throw > [4]: https://luajit.org/extensions.html#exceptions > [5]: https://github.com/tarantool/luajit/commit/ed412cd9f55fe87fd32a69c86e1732690fc5c1b0 > [6]: https://github.com/tarantool/luajit/commit/97699d9ee2467389b6aea21a098e38aff3469b5f > [7]: https://github.com/tarantool/tarantool/issues/1516 > [8]: https://www.freelists.org/post/luajit/Issue-with-PCALL-in-21 > [9]: https://github.com/tarantool/tarantool/commit/e88c0d21ab765d4c53bed2437c49d77b3ffe4216 This patch resolves #6248, BTW. > --- > > Branch: https://github.com/tarantool/tarantool/tree/skaplun/gh-noticket-refactor-lua-call > See the benchmarks sources here [1]. > > Before patch: > | Encode map: 189851357 mcs, 15.8 K ps > | Encode seq: 187926351 mcs, 16.0 K ps > | Encode str: 185451675 mcs, 16.2 K ps > | Encode dig: 184833396 mcs, 16.2 K ps > > After patch: > | Encode map: 187814261 mcs, 16.0 K ps > | Encode seq: 183755028 mcs, 16.3 K ps > | Encode str: 181571626 mcs, 16.5 K ps > | Encode dig: 181572998 mcs, 16.5 K ps > > Looks like the perf doesn't degrade at least. At first, I would like to emphasize that we have no option for merging or not the fix for this issue. Re benchmarks: It's worth to mention you're measuring two performance critical changes: effect and lower GC pressure. So, it's interesting to see the following benchmarks: * one with disabled GC and GC stats * one with considerable amount of elements on Lua stack, but not triggering stack resize (AFAIU, 200 is too much) Here are my points: * There is no such huge increase as a result of reducing GC pressure * Moving 1-5 8-byte elements is neglible for performance * Moving 200(*) elements as a result of the guest stack resize affects both patched and vanilla versions * measurements are affected by resizing (considering your perf stats) Anyway, though these are kinda independent changes, we see no performance degradation using both of them in a single patch, so I guess we have no reason to worry about. (*) I'm not sure about the exact amount of the elements to be moved. > > [1]: https://gist.github.com/Buristan/3e6d6bf2c722874bec55a8c5a44b98f3 > > src/box/lua/call.c | 71 ++++++++++++++++++++++++++++++++++++---------- > 1 file changed, 56 insertions(+), 15 deletions(-) > > diff --git a/src/box/lua/call.c b/src/box/lua/call.c > index 0315e720c..3b2572096 100644 > --- a/src/box/lua/call.c > +++ b/src/box/lua/call.c > @@ -61,6 +61,8 @@ enum handlers { > HANDLER_CALL, > HANDLER_CALL_BY_REF, > HANDLER_EVAL, > + HANDLER_ENCODE_CALL, > + HANDLER_ENCODE_CALL_16, Minor: Entries are not sorted. > HANDLER_MAX, > }; > > @@ -400,11 +402,26 @@ struct encode_lua_ctx { > struct mpstream *stream; > }; > > +/** > + * Encode call results to msgpack from Lua stack. > + * Lua stack has the following structure -- the last element is > + * lightuserdata pointer to encode_lua_ctx, all other values are > + * arguments to proceed. Typo: s/proceed/process/. > + * The function encodes all given Lua objects to msgpack stream > + * from context, sets port's size and returns no value on the Lua > + * stack. > + * XXX: This function *MUST* be called under lua_pcall(), because > + * luamp_encode() may raise an error. > + */ > +/** > + * Encode call_16 results to msgpack from Lua stack. > + * Lua stack has the following structure -- the last element is > + * lightuserdata pointer to encode_lua_ctx, all other values are > + * arguments to proceed. Ditto. > + * The function encodes all given Lua objects to msgpack stream > + * from context, sets port's size and returns no value on the Lua > + * stack. > + * XXX: This function *MUST* be called under lua_pcall(), because > + * luamp_encode() may raise an error. > + */ > @@ -450,13 +482,20 @@ port_lua_do_dump(struct port *base, struct mpstream *stream, > struct encode_lua_ctx ctx; > ctx.port = port; > ctx.stream = stream; > - struct lua_State *L = tarantool_L; > - int top = lua_gettop(L); > - if (lua_cpcall(L, handler, &ctx) != 0) { > - luaT_toerror(port->L); > + lua_State *L = port->L; > + /* > + * At the moment Lua stack holds only values to encode. > + * Insert corresponding encoder to the bottom and push > + * encode context as lightuserdata to the top. > + */ > + const int size = lua_gettop(L); > + lua_rawgeti(L, LUA_REGISTRYINDEX, execute_lua_refs[handler]); > + assert(lua_isfunction(L, -1) && lua_iscfunction(L, -1)); > + lua_insert(L, 1); Side note: I don't like this line, like all we do. The only better approach in my head is to implement something similar to VARG frame, but I doubt this approach have no pure Lua violations. Let's return to this later a bit. > + lua_pushlightuserdata(L, &ctx); > + /* nargs -- all arguments + lightuserdata. */ > + if (luaT_call(L, size + 1, 0) != 0) > return -1; > - } > - lua_settop(L, top); > return port->size; > } > > @@ -1049,6 +1088,8 @@ box_lua_call_init(struct lua_State *L) > [HANDLER_CALL] = execute_lua_call, > [HANDLER_CALL_BY_REF] = execute_lua_call_by_ref, > [HANDLER_EVAL] = execute_lua_eval, > + [HANDLER_ENCODE_CALL] = encode_lua_call, > + [HANDLER_ENCODE_CALL_16] = encode_lua_call_16, Minor: Entries are also not sorted. > }; > > for (int i = 0; i < HANDLER_MAX; i++) { > -- > 2.31.0 > -- Best regards, IM