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 5E2346EC55; Wed, 8 Sep 2021 21:22:07 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 5E2346EC55 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1631125327; bh=+KnnkX2fL/iPOHbIDTFa9cBRco8KL8YhCU3HGy9cHCA=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=NxU6NmNizOM7LIPGknyXrnsN6W27mtX/MNQbRtqJ+nwxrjBpKNA/telzBiK2LP55z ad4VHqWL3JJfjbjyfCyEAi4hbrZcCxhXBU7DOD6wv4lPPoRRJZXDvvDmXdSlGbJqnm xbCEpKniNP6LujoY3DQuL/0FQF+qlYQvZIX2lWRo= Received: from smtp37.i.mail.ru (smtp37.i.mail.ru [94.100.177.97]) (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 97B6D6E469 for ; Wed, 8 Sep 2021 21:20:06 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 97B6D6E469 Received: by smtp37.i.mail.ru with esmtpa (envelope-from ) id 1mO2B3-0003tR-KU; Wed, 08 Sep 2021 21:20:06 +0300 To: v.shpilevoy@tarantool.org, imun@tarantool.org Date: Wed, 8 Sep 2021 21:20:02 +0300 Message-Id: <2277f244b5bed55c1a4302310889c7e54ac0872a.1631124536.git.babinoleg@mail.ru> X-Mailer: git-send-email 2.32.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-4EC0790: 10 X-7564579A: 646B95376F6C166E X-77F55803: 4F1203BC0FB41BD91AE02D33A9C88A2FF3F790D2CFB1565D68082CE688654CB400894C459B0CD1B9EAB9801818D9592EB5D7EB73DBC90D3594E6721A1D1978B7A41EFFA2D20C5292 X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE7B7733D0215A2F71AEA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F79006374F638C8F0F4AA0FB8638F802B75D45FF36EB9D2243A4F8B5A6FCA7DBDB1FC311F39EFFDF887939037866D6147AF826D89663AEEEED142A2D38CDA0D5F2D74E91117882F4460429724CE54428C33FAD305F5C1EE8F4F765FC974A882099E279BDA471835C12D1D9774AD6D5ED66289B52BA9C0B312567BB23117882F446042972877693876707352033AC447995A7AD18618001F51B5FD3F9D2E47CDBA5A96583BA9C0B312567BB2376E601842F6C81A19E625A9149C048EE140C956E756FBB7A9D765CF6BB0EE041D8FC6C240DEA7642DBF02ECDB25306B2B78CF848AE20165D0A6AB1C7CE11FEE317119E5299B287EEC0837EA9F3D19764C4224003CC836476EA7A3FFF5B025636E2021AF6380DFAD1A18204E546F3947CB11811A4A51E3B096D1867E19FE1407959CC434672EE6371089D37D7C0E48F6C8AA50765F79006376A91CFDE938F542CEFF80C71ABB335746BA297DBC24807EABDAD6C7F3747799A X-B7AD71C0: AC4F5C86D027EB782CDD5689AFBDA7A213B5FB47DCBC3458F0AFF96BAACF4158235E5A14AD4A4A4625E192CAD1D9E79D2AE6C3BEB5DE9A2692A0C52F1B74B012 X-C1DE0DAB: C20DE7B7AB408E4181F030C43753B8186998911F362727C414F749A5E30D975CBF3286B3348795C6F29B0CDC8BBFC443B2F40BE3F4B15FC29C2B6934AE262D3EE7EAB7254005DCED7532B743992DF240BDC6A1CF3F042BAD6DF99611D93F60EFCCE3E035A672CDEE699F904B3F4130E343918A1A30D5E7FCCB5012B2E24CD356 X-C8649E89: 4E36BF7865823D7055A7F0CF078B5EC49A30900B95165D3473688ED311681BF0D5088748C81885BC2122025EB9A208FF7BD2B0AF05C124CFECEFC91E3934C33A1D7E09C32AA3244CF5A5E689BD6782BADBBBF31AD9A26E3D408A6A02710B7304927AC6DF5659F194 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2biojV8xpaxME9p9RJyfW5UcIsQ== X-Mailru-Sender: 583F1D7ACE8F49BD1042885CEC987B6B74342559F1471A1B273B1C6D878C35F7B67A942A63B4089A7019711D9D5B048E1458020726E2BC9FD5ECBA0B92C0A936CDC7563AA7CEBD287402F9BA4338D657ED14614B50AE0675 X-Mras: Ok Subject: [Tarantool-patches] [PATCH v4 4/4] fiber: keep reference to userdata if fiber created once 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: Oleg Babin via Tarantool-patches Reply-To: olegrok@tarantool.org Cc: tarantool-patches@dev.tarantool.org Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" From: Oleg Babin This patch reworks approach to fiber management in Lua. Before this patch each action that should return fiber led to new userdata creation that was quite slow and made GC suffer. This patch introduces new field in struct fiber to store a reference to userdata that was created once for a fiber. It allows speedup operations as fiber.self() and fiber.id(). Simple benchmark shows that access to fiber storage is faster in two times, fiber.find() - 2-3 times and fiber.new/create functions don't have any changes. --- src/lib/core/fiber.c | 2 + src/lib/core/fiber.h | 5 ++ src/lua/fiber.c | 110 +++++++++++++------------------------------ 3 files changed, 39 insertions(+), 78 deletions(-) diff --git a/src/lib/core/fiber.c b/src/lib/core/fiber.c index b7699372a..3e19f131b 100644 --- a/src/lib/core/fiber.c +++ b/src/lib/core/fiber.c @@ -896,6 +896,7 @@ fiber_recycle(struct fiber *fiber) fiber->wait_pad = NULL; memset(&fiber->storage, 0, sizeof(fiber->storage)); fiber->storage.lua.storage_ref = FIBER_LUA_NOREF; + fiber->storage.lua.fid_ref = FIBER_LUA_NOREF; unregister_fid(fiber); fiber->fid = 0; region_free(&fiber->gc); @@ -1238,6 +1239,7 @@ fiber_new_ex(const char *name, const struct fiber_attr *fiber_attr, } memset(fiber, 0, sizeof(struct fiber)); fiber->storage.lua.storage_ref = FIBER_LUA_NOREF; + fiber->storage.lua.fid_ref = FIBER_LUA_NOREF; if (fiber_stack_create(fiber, &cord()->slabc, fiber_attr->stack_size)) { diff --git a/src/lib/core/fiber.h b/src/lib/core/fiber.h index 9584b1611..9ac0cbb9f 100644 --- a/src/lib/core/fiber.h +++ b/src/lib/core/fiber.h @@ -625,6 +625,11 @@ struct fiber { * Should not be used in other fibers. */ struct lua_State *stack; + /** + * Optional reference to userdata + * represented current fiber id in Lua. + */ + int fid_ref; /** * Optional fiber.storage Lua reference. */ diff --git a/src/lua/fiber.c b/src/lua/fiber.c index 96aa73b19..12836da69 100644 --- a/src/lua/fiber.c +++ b/src/lua/fiber.c @@ -87,27 +87,26 @@ luaL_testcancel(struct lua_State *L) static const char *fiberlib_name = "fiber"; /** - * @pre: stack top contains a table - * @post: sets table field specified by name of the table on top - * of the stack to a weak kv table and pops that weak table. + * Trigger invoked when the fiber has stopped execution of its + * current request. Only purpose - delete storage.lua.fid_ref and + * storage.lua.storage_ref keeping a reference of Lua + * fiber and fiber.storage objects. Unlike Lua stack, + * Lua fiber storage may be created not only for fibers born from + * Lua land. For example, an IProto request may execute a Lua + * function, which can create the storage. Trigger guarantees, + * that even for non-Lua fibers the Lua storage is destroyed. */ -static void -lbox_create_weak_table(struct lua_State *L, const char *name) +static int +lbox_fiber_on_stop(struct trigger *trigger, void *event) { - lua_newtable(L); - /* and a metatable */ - lua_newtable(L); - /* weak keys and values */ - lua_pushstring(L, "kv"); - /* pops 'kv' */ - lua_setfield(L, -2, "__mode"); - /* pops the metatable */ - lua_setmetatable(L, -2); - /* assigns and pops table */ - lua_setfield(L, -2, name); - /* gets memoize back. */ - lua_getfield(L, -1, name); - assert(! lua_isnil(L, -1)); + struct fiber *f = event; + luaL_unref(tarantool_L, LUA_REGISTRYINDEX, f->storage.lua.storage_ref); + f->storage.lua.storage_ref = FIBER_LUA_NOREF; + luaL_unref(tarantool_L, LUA_REGISTRYINDEX, f->storage.lua.fid_ref); + f->storage.lua.fid_ref = FIBER_LUA_NOREF; + trigger_clear(trigger); + free(trigger); + return 0; } /** @@ -116,42 +115,26 @@ lbox_create_weak_table(struct lua_State *L, const char *name) static void lbox_pushfiber(struct lua_State *L, struct fiber *f) { - /* - * Use 'memoize' pattern and keep a single userdata for - * the given fiber. This is important to not run __gc - * twice for a copy of an attached fiber -- __gc should - * not remove attached fiber's coro prematurely. - */ - luaL_getmetatable(L, fiberlib_name); - lua_getfield(L, -1, "memoize"); - if (lua_isnil(L, -1)) { - /* first access - instantiate memoize */ - /* pop the nil */ - lua_pop(L, 1); - /* create memoize table */ - lbox_create_weak_table(L, "memoize"); - } - /* Find out whether the fiber is already in the memoize table. */ - uint64_t fid = f->fid; - luaL_pushuint64(L, fid); - lua_gettable(L, -2); - if (lua_isnil(L, -1)) { - /* no userdata for fiber created so far */ - /* pop the nil */ - lua_pop(L, 1); - /* push the key back */ - luaL_pushuint64(L, fid); + int fid_ref = f->storage.lua.fid_ref; + if (fid_ref == FIBER_LUA_NOREF) { + struct trigger *t = malloc(sizeof(*t)); + if (t == NULL) { + diag_set(OutOfMemory, sizeof(*t), "malloc", "t"); + luaT_error(L); + } + trigger_create(t, lbox_fiber_on_stop, NULL, (trigger_f0)free); + trigger_add(&f->on_stop, t); + + uint64_t fid = f->fid; /* create a new userdata */ uint64_t *ptr = lua_newuserdata(L, sizeof(*ptr)); *ptr = fid; luaL_getmetatable(L, fiberlib_name); lua_setmetatable(L, -2); - /* memoize it */ - lua_settable(L, -3); - luaL_pushuint64(L, fid); - /* get it back */ - lua_gettable(L, -2); + fid_ref = luaL_ref(L, LUA_REGISTRYINDEX); + f->storage.lua.fid_ref = fid_ref; } + lua_rawgeti(L, LUA_REGISTRYINDEX, fid_ref); } static struct fiber * @@ -669,41 +652,12 @@ lbox_fiber_name(struct lua_State *L) } } -/** - * Trigger invoked when the fiber has stopped execution of its - * current request. Only purpose - delete storage.lua.storage_ref keeping - * a reference of Lua fiber.storage object. Unlike Lua stack, - * Lua fiber storage may be created not only for fibers born from - * Lua land. For example, an IProto request may execute a Lua - * function, which can create the storage. Trigger guarantees, - * that even for non-Lua fibers the Lua storage is destroyed. - */ -static int -lbox_fiber_on_stop(struct trigger *trigger, void *event) -{ - struct fiber *f = (struct fiber *) event; - int storage_ref = f->storage.lua.storage_ref; - luaL_unref(tarantool_L, LUA_REGISTRYINDEX, storage_ref); - f->storage.lua.storage_ref = FIBER_LUA_NOREF; - trigger_clear(trigger); - free(trigger); - return 0; -} - static int lbox_fiber_storage(struct lua_State *L) { struct fiber *f = lbox_checkfiber(L, 1); int storage_ref = f->storage.lua.storage_ref; if (storage_ref == FIBER_LUA_NOREF) { - struct trigger *t = (struct trigger *) - malloc(sizeof(*t)); - if (t == NULL) { - diag_set(OutOfMemory, sizeof(*t), "malloc", "t"); - return luaT_error(L); - } - trigger_create(t, lbox_fiber_on_stop, NULL, (trigger_f0) free); - trigger_add(&f->on_stop, t); lua_newtable(L); /* create local storage on demand */ storage_ref = luaL_ref(L, LUA_REGISTRYINDEX); f->storage.lua.storage_ref = storage_ref; -- 2.32.0