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 140F86FC8F; Thu, 25 Mar 2021 00:30:12 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 140F86FC8F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1616621412; bh=2MPE/1+fxde3H+CITY3QcHTCvee2lZEsWK6y5ENYvAs=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=wyrTHObKCfTMAzJBiRBydzgbGS0PyaWyQXqRcNWSolpTWMyZsKQi1XFA4LIxwMdKU v80+qvaG3Id9zLJ7hXFUYtMU1lNYnx11BTJJMAlvev3dP1j5/YiebR/eOZpl8dmsfB acfAvVBkN7BcZcALHFPiXC1eX13SFJZdXPSnnw1o= Received: from smtp48.i.mail.ru (smtp48.i.mail.ru [94.100.177.108]) (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 14FE66AAB3 for ; Thu, 25 Mar 2021 00:24:51 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 14FE66AAB3 Received: by smtp48.i.mail.ru with esmtpa (envelope-from ) id 1lPAzh-0004ib-Rv; Thu, 25 Mar 2021 00:24:50 +0300 To: tarantool-patches@dev.tarantool.org, kyukhin@tarantool.org Date: Wed, 24 Mar 2021 22:24:31 +0100 Message-Id: <3d7bf8d84d8ed66823b52404bdd7a7fb37d836e5.1616620860.git.v.shpilevoy@tarantool.org> X-Mailer: git-send-email 2.24.3 (Apple Git-128) In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-7564579A: B8F34718100C35BD X-77F55803: 4F1203BC0FB41BD9064ADF4728AA0EE9AECA9F3C9C9885BEE78E91CF33279E24182A05F5380850404FAF9E1B354CF105B1A62CEC25499FF20D8CAC1DBC59C38E57BDBE8FBA478AAE X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE7EEF2A6A9DCF3640FC2099A533E45F2D0395957E7521B51C2CFCAF695D4D8E9FCEA1F7E6F0F101C6778DA827A17800CE74D0D2DEF2EB846B0EA1F7E6F0F101C67CDEEF6D7F21E0D1D174C73DBBBFC76641763F9D2EFCE7A1AEA2D033D25F613FEE8B3CECEF82F8422389733CBF5DBD5E913377AFFFEAFD269176DF2183F8FC7C07E7E81EEA8A9722B8941B15DA834481FCF19DD082D7633A0EF3E4896CB9E6436389733CBF5DBD5E9D5E8D9A59859A8B65FF0BFC5AEE34BE6CC7F00164DA146DA6F5DAA56C3B73B237318B6A418E8EAB8D32BA5DBAC0009BE9E8FC8737B5C224995295AD1C67E969D76E601842F6C81A12EF20D2F80756B5F7E9C4E3C761E06A776E601842F6C81A127C277FBC8AE2E8BBD1D0C6335D5E3173AA81AA40904B5D9DBF02ECDB25306B2201CA6A4E26CD07C3BBE47FD9DD3FB595F5C1EE8F4F765FC72CEEB2601E22B091A620F70A64A45A99449624AB7ADAF372E808ACE2090B5E1725E5C173C3A84C33D321E7403792E343D7D993A0B92D134F5D81C698A659EA775ECD9A6C639B01BC09775C1D3CA48CFC9BE88FFEDFA497A35872C767BF85DA22EF20D2F80756B5F40A5AABA2AD3711975ECD9A6C639B01B78DA827A17800CE74ABCC139FF3F849B731C566533BA786A40A5AABA2AD371193C9F3DD0FB1AF5EB417FD7EC7EC0BD913C9F3DD0FB1AF5EB4E70A05D1297E1BBCB5012B2E24CD356 X-B7AD71C0: AC4F5C86D027EB782CDD5689AFBDA7A2368A440D3B0F6089093C9A16E5BC824AC8B6CDF511875BC4E8F7B195E1C97831148145A0506FFD48E78E5B5B57A3F822 X-C1DE0DAB: C20DE7B7AB408E4181F030C43753B8183A4AFAF3EA6BDC44C234C8B12C006B7A1763F9D2EFCE7A1AEA2D033D25F613FE7EAD490EE27E6CAEB1881A6453793CE9C32612AADDFBE061C61BE10805914D3804EBA3D8E7E5B87ABF8C51168CD8EBDB63AF70AF8205D7DCDC48ACC2A39D04F89CDFB48F4795C241BDAD6C7F3747799A X-C8649E89: 4E36BF7865823D7055A7F0CF078B5EC49A30900B95165D340DAE5B306C240CF53233609F10966648D4E4C9D5BC766B3F0CBE9F776216AA5DE93065C8DF8556271D7E09C32AA3244CB10601483E2B3AA8669A1702061D0EA760759606DA2E136A729B2BEF169E0186 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2biojjqzNotmU+gfij0N9UdDP8A== X-Mailru-Sender: 504CC1E875BF3E7D9BC0E5172ADA3110A906815429F9D960FABCD61F10314346ADA57E69902965B207784C02288277CA03E0582D3806FB6A5317862B1921BA260ED6CFD6382C13A6112434F685709FCF0DA7A0AF5A3A8387 X-Mras: Ok Subject: [Tarantool-patches] [PATCH 05/15] cord_buf: introduce cord_buf API 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: Vladislav Shpilevoy via Tarantool-patches Reply-To: Vladislav Shpilevoy Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" There was a global ibuf object called tarantool_lua_ibuf. It was used in all the places working with Lua which didn't have yields, and where fiber's region could be potentially slower due to not being able to guarantee the allocated memory is contiguous. Yields during the ibuf usage were prohibited because another fiber would take the same ibuf and override its previous content which was still used by another fiber. But it wasn't taken into account that there is Lua GC. It can be invoked from any Lua function in Lua C code, and almost on any line in the Lua scripts. During GC some deleted objects might have GC handlers installed as __gc metamethods. From the handler they could call Tarantool functions, including the ones using the global ibuf. Therefore ibuf could be overridden not only at yields, but almost in any moment. Because with the Lua GC at hand, the multitasking is not strictly "cooperative" anymore. It is necessary to implement ownership for the global buffer. The patch prepares the API for this: the buffer is moved to its own file, and has methods take(), put(), and drop(). Take() is supposed to make the current fiber own the buffer. Put() makes it available again. Drop() does the same but also clears the buffer (frees its memory). The ownership itself is a subject for the next patches. Here only the API is prepared. The patch "hits" performance a little. Previously the get of buffer.IBUF_SHARED cost around 1 ns. Now cord_ibuf_take() + cord_ibuf_put() cost around 5 ns together. The next patches will make it worse, up to 15 ns until #5871 is done. Part of #5632 (cherry picked from commit ade45685f4fdab47204e11cbd82048bb68bbd03b) --- extra/exports | 4 ++- src/CMakeLists.txt | 1 + src/box/lua/schema.lua | 47 ++++++++++++++++++++++++----------- src/box/lua/tuple.c | 28 ++++++++++----------- src/box/lua/tuple.lua | 14 +++++++---- src/cord_buf.c | 47 +++++++++++++++++++++++++++++++++++ src/cord_buf.h | 45 +++++++++++++++++++++++++++++++++ src/lua/buffer.lua | 51 ++++++++++++++++++++++++++++++++++++-- src/lua/iconv.lua | 8 +++--- src/lua/init.c | 3 --- src/lua/msgpack.c | 6 ++--- src/lua/msgpackffi.lua | 7 +++--- src/lua/socket.lua | 14 +++++------ src/lua/utf8.c | 16 +++++++----- src/lua/utils.h | 1 - test/unit/luaT_tuple_new.c | 4 --- 16 files changed, 229 insertions(+), 67 deletions(-) create mode 100644 src/cord_buf.c create mode 100644 src/cord_buf.h diff --git a/extra/exports b/extra/exports index 94e04264e..91094206d 100644 --- a/extra/exports +++ b/extra/exports @@ -44,7 +44,6 @@ tnt_iconv exception_get_string exception_get_int -tarantool_lua_ibuf uuid_nil tt_uuid_create tt_uuid_str @@ -111,6 +110,9 @@ fiber_cond_signal fiber_cond_broadcast fiber_cond_wait_timeout fiber_cond_wait +cord_ibuf_drop +cord_ibuf_put +cord_ibuf_take cord_slab_cache coio_wait coio_close diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d14997413..1e840aab9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -107,6 +107,7 @@ set (core_sources http_parser.c coll.c coll_def.c + cord_buf.c ) if (TARGET_OS_NETBSD) diff --git a/src/box/lua/schema.lua b/src/box/lua/schema.lua index a23fe0813..513dab1be 100644 --- a/src/box/lua/schema.lua +++ b/src/box/lua/schema.lua @@ -1,6 +1,7 @@ -- schema.lua (internal file) -- local ffi = require('ffi') +local buffer = require('buffer') local msgpack = require('msgpack') local msgpackffi = require('msgpackffi') local fun = require('fun') @@ -20,6 +21,8 @@ local tuple_encode = box.tuple.encode local tuple_bless = box.tuple.bless local is_tuple = box.tuple.is assert(tuple_encode ~= nil and tuple_bless ~= nil and is_tuple ~= nil) +local cord_ibuf_take = buffer.internal.cord_ibuf_take +local cord_ibuf_put = buffer.internal.cord_ibuf_put local INT64_MIN = tonumber64('-9223372036854775808') local INT64_MAX = tonumber64('9223372036854775807') @@ -1145,9 +1148,12 @@ base_index_mt.__len = base_index_mt.len -- min and max base_index_mt.min_ffi = function(index, key) check_index_arg(index, 'min') - local pkey, pkey_end = tuple_encode(key) - if builtin.box_index_min(index.space_id, index.id, - pkey, pkey_end, ptuple) ~= 0 then + local ibuf = cord_ibuf_take() + local pkey, pkey_end = tuple_encode(ibuf, key) + local nok = builtin.box_index_min(index.space_id, index.id, pkey, pkey_end, + ptuple) ~= 0 + cord_ibuf_put(ibuf) + if nok then box.error() -- error elseif ptuple[0] ~= nil then return tuple_bless(ptuple[0]) @@ -1162,9 +1168,12 @@ base_index_mt.min_luac = function(index, key) end base_index_mt.max_ffi = function(index, key) check_index_arg(index, 'max') - local pkey, pkey_end = tuple_encode(key) - if builtin.box_index_max(index.space_id, index.id, - pkey, pkey_end, ptuple) ~= 0 then + local ibuf = cord_ibuf_take() + local pkey, pkey_end = tuple_encode(ibuf, key) + local nok = builtin.box_index_max(index.space_id, index.id, pkey, pkey_end, + ptuple) ~= 0 + cord_ibuf_put(ibuf) + if nok then box.error() -- error elseif ptuple[0] ~= nil then return tuple_bless(ptuple[0]) @@ -1197,10 +1206,12 @@ end -- iteration base_index_mt.pairs_ffi = function(index, key, opts) check_index_arg(index, 'pairs') - local pkey, pkey_end = tuple_encode(key) + local ibuf = cord_ibuf_take() + local pkey, pkey_end = tuple_encode(ibuf, key) local itype = check_iterator_type(opts, pkey + 1 >= pkey_end); local keybuf = ffi.string(pkey, pkey_end - pkey) + cord_ibuf_put(ibuf) local pkeybuf = ffi.cast('const char *', keybuf) local cdata = builtin.box_index_iterator(index.space_id, index.id, itype, pkeybuf, pkeybuf + #keybuf); @@ -1224,10 +1235,12 @@ end -- index subtree size base_index_mt.count_ffi = function(index, key, opts) check_index_arg(index, 'count') - local pkey, pkey_end = tuple_encode(key) + local ibuf = cord_ibuf_take() + local pkey, pkey_end = tuple_encode(ibuf, key) local itype = check_iterator_type(opts, pkey + 1 >= pkey_end); local count = builtin.box_index_count(index.space_id, index.id, itype, pkey, pkey_end); + cord_ibuf_put(ibuf) if count == -1 then box.error() end @@ -1242,9 +1255,12 @@ end base_index_mt.get_ffi = function(index, key) check_index_arg(index, 'get') - local key, key_end = tuple_encode(key) - if builtin.box_index_get(index.space_id, index.id, - key, key_end, ptuple) ~= 0 then + local ibuf = cord_ibuf_take() + local key, key_end = tuple_encode(ibuf, key) + local nok = builtin.box_index_get(index.space_id, index.id, key, key_end, + ptuple) ~= 0 + cord_ibuf_put(ibuf) + if nok then return box.error() -- error elseif ptuple[0] ~= nil then return tuple_bless(ptuple[0]) @@ -1275,13 +1291,16 @@ end base_index_mt.select_ffi = function(index, key, opts) check_index_arg(index, 'select') - local key, key_end = tuple_encode(key) + local ibuf = cord_ibuf_take() + local key, key_end = tuple_encode(ibuf, key) local iterator, offset, limit = check_select_opts(opts, key + 1 >= key_end) local port = ffi.cast('struct port *', port_tuple) - if builtin.box_select(index.space_id, index.id, - iterator, offset, limit, key, key_end, port) ~= 0 then + local nok = builtin.box_select(index.space_id, index.id, iterator, offset, + limit, key, key_end, port) ~= 0 + cord_ibuf_put(ibuf) + if nok then return box.error() end diff --git a/src/box/lua/tuple.c b/src/box/lua/tuple.c index 00ac3b44c..ad056a3bc 100644 --- a/src/box/lua/tuple.c +++ b/src/box/lua/tuple.c @@ -36,6 +36,7 @@ #include "diag.h" /* diag_set() */ #include #include +#include "cord_buf.h" #include #include "box/tuple.h" @@ -279,16 +280,18 @@ luaT_tuple_encode(struct lua_State *L, int idx, size_t *tuple_len_ptr) box_tuple_t * luaT_tuple_new(struct lua_State *L, int idx, box_tuple_format_t *format) { - struct ibuf *ibuf = tarantool_lua_ibuf; - ibuf_reset(ibuf); + struct ibuf *ibuf = cord_ibuf_take(); size_t tuple_len; + box_tuple_t *tuple; char *tuple_data = luaT_tuple_encode_on_lua_ibuf(L, idx, &tuple_len, ibuf); - if (tuple_data == NULL) - return NULL; - box_tuple_t *tuple = box_tuple_new(format, tuple_data, - tuple_data + tuple_len); - ibuf_reinit(ibuf); + if (tuple_data == NULL) { + tuple = NULL; + } else { + tuple = box_tuple_new(format, tuple_data, + tuple_data + tuple_len); + } + cord_ibuf_drop(ibuf); return tuple; } @@ -307,12 +310,11 @@ lbox_tuple_new(lua_State *L) */ box_tuple_format_t *fmt = box_tuple_format_default(); if (argc != 1 || (!lua_istable(L, 1) && !luaT_istuple(L, 1))) { - struct ibuf *buf = tarantool_lua_ibuf; - ibuf_reset(buf); + struct ibuf *buf = cord_ibuf_take(); luaT_tuple_encode_values(L, buf); /* may raise */ struct tuple *tuple = box_tuple_new(fmt, buf->buf, buf->buf + ibuf_used(buf)); - ibuf_reinit(buf); + cord_ibuf_drop(buf); if (tuple == NULL) return luaT_error(L); luaT_pushtuple(L, tuple); @@ -586,8 +588,7 @@ lbox_tuple_transform(struct lua_State *L) return 1; } - struct ibuf *buf = tarantool_lua_ibuf; - ibuf_reset(buf); + struct ibuf *buf = cord_ibuf_take(); struct mpstream stream; mpstream_init(&stream, buf, ibuf_reserve_cb, ibuf_alloc_cb, luamp_error, L); @@ -632,12 +633,11 @@ lbox_tuple_transform(struct lua_State *L) new_tuple = tuple_new(box_tuple_format_default(), new_data, new_data + new_size); region_truncate(region, used); - + cord_ibuf_put(buf); if (new_tuple == NULL) luaT_error(L); luaT_pushtuple(L, new_tuple); - ibuf_reset(buf); return 1; } diff --git a/src/box/lua/tuple.lua b/src/box/lua/tuple.lua index 63ea73e43..186216420 100644 --- a/src/box/lua/tuple.lua +++ b/src/box/lua/tuple.lua @@ -6,6 +6,8 @@ local msgpackffi = require('msgpackffi') local fun = require('fun') local buffer = require('buffer') local internal = require('box.internal') +local cord_ibuf_take = buffer.internal.cord_ibuf_take +local cord_ibuf_put = buffer.internal.cord_ibuf_put ffi.cdef[[ /** \cond public */ @@ -72,9 +74,7 @@ local encode_fix = msgpackffi.internal.encode_fix local encode_array = msgpackffi.internal.encode_array local encode_r = msgpackffi.internal.encode_r -local tuple_encode = function(obj) - local tmpbuf = buffer.IBUF_SHARED - tmpbuf:reset() +local tuple_encode = function(tmpbuf, obj) if obj == nil then encode_fix(tmpbuf, 0x90, 0) -- empty array elseif is_tuple(obj) then @@ -231,8 +231,10 @@ local function tuple_update(tuple, expr) if type(expr) ~= 'table' then error("Usage: tuple:update({ { op, field, arg}+ })") end - local pexpr, pexpr_end = tuple_encode(expr) + local ibuf = cord_ibuf_take() + local pexpr, pexpr_end = tuple_encode(ibuf, expr) local tuple = builtin.box_tuple_update(tuple, pexpr, pexpr_end) + cord_ibuf_put(ibuf) if tuple == nil then return box.error() end @@ -244,8 +246,10 @@ local function tuple_upsert(tuple, expr) if type(expr) ~= 'table' then error("Usage: tuple:upsert({ { op, field, arg}+ })") end - local pexpr, pexpr_end = tuple_encode(expr) + local ibuf = cord_ibuf_take() + local pexpr, pexpr_end = tuple_encode(ibuf, expr) local tuple = builtin.box_tuple_upsert(tuple, pexpr, pexpr_end) + cord_ibuf_put(ibuf) if tuple == nil then return box.error() end diff --git a/src/cord_buf.c b/src/cord_buf.c new file mode 100644 index 000000000..cac508c3d --- /dev/null +++ b/src/cord_buf.c @@ -0,0 +1,47 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright 2010-2021, Tarantool AUTHORS, please see AUTHORS file. + */ +#include "cord_buf.h" +#include "fiber.h" + +#include "small/ibuf.h" + +enum { + /* No any reason why that value. Historical constant. */ + CORD_IBUF_START_CAPACITY = 16384, +}; + +static struct ibuf *cord_buf_global = NULL; + +struct ibuf * +cord_ibuf_take(void) +{ + assert(cord_is_main()); + struct ibuf *buf = cord_buf_global; + if (buf != NULL) { + ibuf_reset(buf); + return buf; + } + buf = malloc(sizeof(*buf)); + if (buf == NULL) + panic("Couldn't allocate thread buffer"); + ibuf_create(buf, &cord()->slabc, CORD_IBUF_START_CAPACITY); + cord_buf_global = buf; + return buf; +} + +void +cord_ibuf_put(struct ibuf *ibuf) +{ + (void)ibuf; + assert(ibuf == cord_buf_global); +} + +void +cord_ibuf_drop(struct ibuf *ibuf) +{ + ibuf_reinit(ibuf); + assert(ibuf == cord_buf_global); +} diff --git a/src/cord_buf.h b/src/cord_buf.h new file mode 100644 index 000000000..59f429c8f --- /dev/null +++ b/src/cord_buf.h @@ -0,0 +1,45 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright 2010-2021, Tarantool AUTHORS, please see AUTHORS file. + */ +#pragma once + +#if defined(__cplusplus) +extern "C" { +#endif /* defined(__cplusplus) */ + +struct ibuf; + +/** + * Take the global ibuf, or allocate a new one if the stash is empty. + */ +struct ibuf * +cord_ibuf_take(void); + +/** + * Put the global ibuf back. + */ +void +cord_ibuf_put(struct ibuf *ibuf); + +/** + * Put the global ibuf back and free its memory. So only the buffer object + * itself is saved to the stash. Main reason why it is a dedicated function is + * because it is often needed from Lua, and allows not to call :recycle() there, + * which would be an additional FFI call before cord_ibuf_put(). + * + * XXX: recycle of the global buffer is a workaround for the ibuf being used in + * some places working with Lua API, where it wasn't wanted to "reuse" it + * anyhow. Instead, the global buffer is used to protect from the buffer leak in + * case it would be created locally, and then a Lua error would be raised. When + * the buffer is global, it is not a problem, because it is reused/recycled + * later. But it hurts the places, where re-usage could be good. Probably it is + * worth to separate take/put() from new/drop() API. Or delete drop() entirely. + */ +void +cord_ibuf_drop(struct ibuf *ibuf); + +#if defined(__cplusplus) +} +#endif /* defined(__cplusplus) */ diff --git a/src/lua/buffer.lua b/src/lua/buffer.lua index a72d8d1f9..398319cf2 100644 --- a/src/lua/buffer.lua +++ b/src/lua/buffer.lua @@ -7,7 +7,15 @@ ffi.cdef[[ struct slab_cache; struct slab_cache * tarantool_lua_slab_cache(); -extern struct ibuf *tarantool_lua_ibuf; + +struct ibuf * +cord_ibuf_take(void); + +void +cord_ibuf_put(struct ibuf *ibuf); + +void +cord_ibuf_drop(struct ibuf *ibuf); struct ibuf { @@ -174,8 +182,47 @@ local function ibuf_new(arg, arg2) errorf('Usage: ibuf([size])') end +-- +-- Cord buffer is useful for the places, where +-- +-- * Want to reuse the already allocated memory which might be stored in the +-- cord buf. Although sometimes the buffer is recycled, so should not rely on +-- being able to reuse it always. When reused, the win is the biggest - +-- becomes about x20 times faster than a new buffer creation (~5ns vs ~100ns); +-- +-- * Want to avoid allocation of a new ibuf because it produces a new GC object +-- which is additional load for Lua GC. Although according to benches it is +-- not super expensive; +-- +-- * Almost always can put the buffer back manually. Not rely on it being +-- recycled automatically. It is recycled, but still should not rely on that; +-- +-- It is important to wrap the C functions, not expose them directly. Because +-- JIT works a bit better when C functions are called as 'ffi.C.func()' than +-- 'func()' with func being cached. The only pros is to cache 'ffi.C' itself. +-- It is quite strange though how having them wrapped into a Lua function is +-- faster than cached directly as C functions. +-- +local function cord_ibuf_take() + return builtin.cord_ibuf_take() +end + +local function cord_ibuf_put(buf) + return builtin.cord_ibuf_put(buf) +end + +local function cord_ibuf_drop(buf) + return builtin.cord_ibuf_drop(buf) +end + +local internal = { + cord_ibuf_take = cord_ibuf_take, + cord_ibuf_put = cord_ibuf_put, + cord_ibuf_drop = cord_ibuf_drop, +} + return { + internal = internal, ibuf = ibuf_new; - IBUF_SHARED = ffi.C.tarantool_lua_ibuf; READAHEAD = READAHEAD; } diff --git a/src/lua/iconv.lua b/src/lua/iconv.lua index e68509dec..732b80514 100644 --- a/src/lua/iconv.lua +++ b/src/lua/iconv.lua @@ -1,6 +1,8 @@ local ffi = require('ffi') local errno = require('errno') local buffer = require('buffer') +local cord_ibuf_take = buffer.internal.cord_ibuf_take +local cord_ibuf_put = buffer.internal.cord_ibuf_put ffi.cdef[[ typedef struct iconv *iconv_t; @@ -33,10 +35,9 @@ local function iconv_convert(iconv, data) -- prepare at lease BUF_SIZE and at most data_len bytes in shared buffer local output_len = data_len >= BUF_SIZE and data_len or BUF_SIZE - local buf = buffer.IBUF_SHARED; + local buf = cord_ibuf_take(); local buf_ptr = char_ptr_arr_t() local buf_left = size_t_arr_t() - buf:reset() while data_left[0] > 0 do buf_ptr[0] = buf:reserve(output_len) @@ -46,6 +47,7 @@ local function iconv_convert(iconv, data) if res == ffi.cast('size_t', -1) then local err = errno() if err ~= E2BIG then + cord_ibuf_put(buf) ffi.C.tnt_iconv(iconv, nil, nil, nil, nil) if err == EINVAL then error('Invalid multibyte sequence') @@ -62,7 +64,7 @@ local function iconv_convert(iconv, data) -- iconv function sets cd's conversion state to the initial state ffi.C.tnt_iconv(iconv, nil, nil, nil, nil) local result = ffi.string(buf.rpos, buf:size()) - buf:reset() + cord_ibuf_put(buf) return result end diff --git a/src/lua/init.c b/src/lua/init.c index d11ab8bf3..3809f6068 100644 --- a/src/lua/init.c +++ b/src/lua/init.c @@ -70,8 +70,6 @@ * The single Lua state of the transaction processor (tx) thread. */ struct lua_State *tarantool_L; -static struct ibuf tarantool_lua_ibuf_body; -struct ibuf *tarantool_lua_ibuf = &tarantool_lua_ibuf_body; /** * The fiber running the startup Lua script */ @@ -429,7 +427,6 @@ tarantool_lua_init(const char *tarantool_bin, int argc, char **argv) if (L == NULL) { panic("failed to initialize Lua"); } - ibuf_create(tarantool_lua_ibuf, tarantool_lua_slab_cache(), 16000); luaL_openlibs(L); tarantool_lua_setpaths(L); diff --git a/src/lua/msgpack.c b/src/lua/msgpack.c index 838f582ff..ea63570bd 100644 --- a/src/lua/msgpack.c +++ b/src/lua/msgpack.c @@ -41,6 +41,7 @@ #include #include +#include "cord_buf.h" #include void @@ -448,8 +449,7 @@ lua_msgpack_encode(lua_State *L) "must be of type 'struct ibuf'"); } } else { - buf = tarantool_lua_ibuf; - ibuf_reset(buf); + buf = cord_ibuf_take(); } size_t used = ibuf_used(buf); @@ -466,7 +466,7 @@ lua_msgpack_encode(lua_State *L) lua_pushinteger(L, ibuf_used(buf) - used); } else { lua_pushlstring(L, buf->buf, ibuf_used(buf)); - ibuf_reinit(buf); + cord_ibuf_drop(buf); } return 1; } diff --git a/src/lua/msgpackffi.lua b/src/lua/msgpackffi.lua index abcbd54fa..ad7998ed1 100644 --- a/src/lua/msgpackffi.lua +++ b/src/lua/msgpackffi.lua @@ -10,6 +10,8 @@ local uint16_ptr_t = ffi.typeof('uint16_t *') local uint32_ptr_t = ffi.typeof('uint32_t *') local uint64_ptr_t = ffi.typeof('uint64_t *') local char_ptr_t = ffi.typeof('char *') +local cord_ibuf_take = buffer.internal.cord_ibuf_take +local cord_ibuf_drop = buffer.internal.cord_ibuf_drop ffi.cdef([[ char * @@ -280,11 +282,10 @@ local function encode_r(buf, obj, level) end local function encode(obj) - local tmpbuf = buffer.IBUF_SHARED - tmpbuf:reset() + local tmpbuf = cord_ibuf_take() encode_r(tmpbuf, obj, 0) local r = ffi.string(tmpbuf.rpos, tmpbuf:size()) - tmpbuf:recycle() + cord_ibuf_drop(tmpbuf) return r end diff --git a/src/lua/socket.lua b/src/lua/socket.lua index 7c2b1ac6b..f68270876 100644 --- a/src/lua/socket.lua +++ b/src/lua/socket.lua @@ -10,6 +10,8 @@ local fiber = require('fiber') local fio = require('fio') local log = require('log') local buffer = require('buffer') +local cord_ibuf_take = buffer.internal.cord_ibuf_take +local cord_ibuf_drop = buffer.internal.cord_ibuf_drop local format = string.format @@ -293,19 +295,15 @@ local function socket_sysread(self, arg1, arg2) error('socket:sysread(): size can not be negative') end - local buf = buffer.IBUF_SHARED - buf:reset() + local buf = cord_ibuf_take() local p = buf:alloc(size) local res = sysread(self, p, size) if res then - local str = ffi.string(p, res) - buf:recycle() - return str - else - buf:recycle() - return res + res = ffi.string(p, res) end + cord_ibuf_drop(buf) + return res end local function socket_nonblock(self, nb) diff --git a/src/lua/utf8.c b/src/lua/utf8.c index 6d3e4d39a..0d9c49a8b 100644 --- a/src/lua/utf8.c +++ b/src/lua/utf8.c @@ -33,11 +33,10 @@ #include #include "lua/utils.h" #include "lua/utf8.h" +#include "cord_buf.h" #include "diag.h" #include "small/ibuf.h" -extern struct ibuf *tarantool_lua_ibuf; - /** Default universal casemap for case transformations. */ static UCaseMap *root_map = NULL; @@ -54,12 +53,13 @@ utf8_str_to_case(struct lua_State *L, const char *src, int src_bsize, int i = 0; int dst_bsize = src_bsize; (void) i; + struct ibuf *ibuf = cord_ibuf_take(); do { UErrorCode err = U_ZERO_ERROR; - ibuf_reset(tarantool_lua_ibuf); - char *dst = ibuf_alloc(tarantool_lua_ibuf, dst_bsize); + char *dst = ibuf_alloc(ibuf, dst_bsize); if (dst == NULL) { diag_set(OutOfMemory, dst_bsize, "ibuf_alloc", "dst"); + cord_ibuf_put(ibuf); return luaT_error(L); } int real_bsize; @@ -75,11 +75,13 @@ utf8_str_to_case(struct lua_State *L, const char *src, int src_bsize, if (err == U_ZERO_ERROR || err == U_STRING_NOT_TERMINATED_WARNING) { lua_pushlstring(L, dst, real_bsize); + cord_ibuf_put(ibuf); return 1; } else if (err == U_BUFFER_OVERFLOW_ERROR) { assert(real_bsize > dst_bsize); dst_bsize = real_bsize; } else { + cord_ibuf_put(ibuf); lua_pushnil(L); lua_pushstring(L, tt_sprintf("error during ICU case "\ "transform: %s", @@ -251,9 +253,10 @@ utf8_char(struct lua_State *L) return 1; } /* Slow way - use dynamic buffer. */ - ibuf_reset(tarantool_lua_ibuf); - char *str = ibuf_alloc(tarantool_lua_ibuf, top * U8_MAX_LENGTH); + struct ibuf *ibuf = cord_ibuf_take(); + char *str = ibuf_alloc(ibuf, top * U8_MAX_LENGTH); if (str == NULL) { + cord_ibuf_put(ibuf); diag_set(OutOfMemory, top * U8_MAX_LENGTH, "ibuf_alloc", "str"); return luaT_error(L); @@ -263,6 +266,7 @@ utf8_char(struct lua_State *L) U8_APPEND_UNSAFE(str, len, c); } lua_pushlstring(L, str, len); + cord_ibuf_put(ibuf); return 1; } diff --git a/src/lua/utils.h b/src/lua/utils.h index cc2e4211f..a61212102 100644 --- a/src/lua/utils.h +++ b/src/lua/utils.h @@ -66,7 +66,6 @@ typedef struct ibuf box_ibuf_t; * snprintf(m_errmsg, sizeof(m_errmsg), "%s", msg ? msg : ""); */ extern struct lua_State *tarantool_L; -extern struct ibuf *tarantool_lua_ibuf; /** \cond public */ diff --git a/test/unit/luaT_tuple_new.c b/test/unit/luaT_tuple_new.c index dcf16ef02..60bc522dc 100644 --- a/test/unit/luaT_tuple_new.c +++ b/test/unit/luaT_tuple_new.c @@ -25,8 +25,6 @@ * box/tuple.test.lua. */ -extern struct ibuf *tarantool_lua_ibuf; - uint32_t min_u32(uint32_t a, uint32_t b) { @@ -180,8 +178,6 @@ main() memory_init(); fiber_init(fiber_c_invoke); - ibuf_create(tarantool_lua_ibuf, &cord()->slabc, 16000); - struct lua_State *L = luaL_newstate(); luaL_openlibs(L); -- 2.24.3 (Apple Git-128)