[tarantool-patches] [PATCH 1/1] netbox: optimize body decoding
Vladislav Shpilevoy
v.shpilevoy at tarantool.org
Mon May 14 14:41:14 MSK 2018
Now netbox decodes body twice: MessagePack -> Lua, Lua -> tuples.
Lets do MessagePack -> tuples.
Part of #3333
---
Branch: https://github.com/tarantool/tarantool/tree/gh-3333-netbox-high-cpu
Issue: https://github.com/tarantool/tarantool/issues/3333
src/box/lua/net_box.c | 42 ++++++++++++++++++++++++++++++++++++++++
src/box/lua/net_box.lua | 51 +++++++++++++++++++++----------------------------
2 files changed, 64 insertions(+), 29 deletions(-)
diff --git a/src/box/lua/net_box.c b/src/box/lua/net_box.c
index 04fe70b03..3d9479283 100644
--- a/src/box/lua/net_box.c
+++ b/src/box/lua/net_box.c
@@ -38,6 +38,7 @@
#include "box/iproto_constants.h"
#include "box/lua/tuple.h" /* luamp_convert_tuple() / luamp_convert_key() */
#include "box/xrow.h"
+#include "box/tuple.h"
#include "lua/msgpack.h"
#include "third_party/base64.h"
@@ -555,6 +556,46 @@ handle_error:
return 2;
}
+/**
+ * Decode Tarantool response body.
+ * @param Lua stack[1] Raw MessagePack pointer.
+ * @param Lua stack[2] End of body pointer.
+ * @retval Decoded body.
+ */
+static int
+netbox_decode_body(struct lua_State *L)
+{
+ uint32_t ctypeid;
+ const char *data = *(const char **)luaL_checkcdata(L, 1, &ctypeid);
+ const char *end = *(const char **)luaL_checkcdata(L, 2, &ctypeid);
+ assert(mp_typeof(*data) == MP_MAP);
+ uint32_t map_size = mp_decode_map(&data);
+ /* Until 2.0 body has no keys except DATA. */
+ assert(map_size == 1);
+ for (uint32_t i = 0; i < map_size; ++i) {
+ uint32_t key = mp_decode_uint(&data);
+ if (key == IPROTO_DATA) {
+ uint32_t count = mp_decode_array(&data);
+ lua_createtable(L, count, 0);
+ struct tuple_format *format =
+ box_tuple_format_default();
+ for (uint32_t j = 0; j < count; ++j) {
+ const char *begin = data;
+ mp_next(&data);
+ struct tuple *tuple =
+ box_tuple_new(format, begin, data);
+ if (tuple == NULL)
+ luaT_error(L);
+ luaT_pushtuple(L, tuple);
+ lua_rawseti(L, -2, j + 1);
+ }
+ }
+ }
+ if (data != end)
+ return luaL_error(L, "invalid xrow length");
+ return 1;
+}
+
int
luaopen_net_box(struct lua_State *L)
{
@@ -572,6 +613,7 @@ luaopen_net_box(struct lua_State *L)
{ "encode_auth", netbox_encode_auth },
{ "decode_greeting",netbox_decode_greeting },
{ "communicate", netbox_communicate },
+ { "decode_body", netbox_decode_body },
{ NULL, NULL}
};
/* luaL_register_module polutes _G */
diff --git a/src/box/lua/net_box.lua b/src/box/lua/net_box.lua
index 46382129f..194a1c86b 100644
--- a/src/box/lua/net_box.lua
+++ b/src/box/lua/net_box.lua
@@ -27,7 +27,6 @@ local encode_auth = internal.encode_auth
local encode_select = internal.encode_select
local decode_greeting = internal.decode_greeting
-local sequence_mt = { __serialize = 'sequence' }
local TIMEOUT_INFINITY = 500 * 365 * 86400
local VSPACE_ID = 281
local VINDEX_ID = 289
@@ -51,30 +50,28 @@ local E_PROC_LUA = box.error.PROC_LUA
local is_final_state = {closed = 1, error = 1}
local function decode_nil(...) end
-local function decode_nop(...) return ... end
-local function decode_tuple(response)
- if response[1] then
- return box.tuple.new(response[1])
- end
+local function decode_data(raw_data, raw_data_end)
+ local response, real_end = decode(raw_data)
+ assert(real_end == raw_data_end, "invalid xrow length")
+ return response[IPROTO_DATA_KEY]
+end
+local function decode_tuple(raw_data, raw_data_end)
+ return internal.decode_body(raw_data, raw_data_end)[1]
end
-local function decode_get(response)
- if response[2] then
+local function decode_get(raw_data, raw_data_end)
+ local body = internal.decode_body(raw_data, raw_data_end)
+ if body[2] then
return nil, box.error.MORE_THAN_ONE_TUPLE
end
- if response[1] then
- return box.tuple.new(response[1])
- end
+ return body[1]
end
-local function decode_select(response)
- setmetatable(response, sequence_mt)
- local tnew = box.tuple.new
- for i, v in pairs(response) do
- response[i] = tnew(v)
- end
- return response
+local function decode_select(raw_data, raw_data_end)
+ return internal.decode_body(raw_data, raw_data_end)
end
-local function decode_count(response)
- return response[1]
+local function decode_count(raw_data, raw_data_end)
+ local response, real_end = decode(raw_data)
+ assert(real_end == raw_data_end, "invalid xrow length")
+ return response[IPROTO_DATA_KEY][1]
end
local method_encoder = {
@@ -103,8 +100,8 @@ local method_encoder = {
local method_decoder = {
ping = decode_nil,
call_16 = decode_select,
- call_17 = decode_nop,
- eval = decode_nop,
+ call_17 = decode_data,
+ eval = decode_data,
insert = decode_tuple,
replace = decode_tuple,
delete = decode_tuple,
@@ -115,7 +112,7 @@ local method_decoder = {
min = decode_get,
max = decode_get,
count = decode_count,
- inject = decode_nop,
+ inject = decode_data,
}
local function next_id(id) return band(id + 1, 0x7FFFFFFF) end
@@ -470,12 +467,8 @@ local function create_transport(host, port, user, password, callback,
end
-- Decode xrow.body[DATA] to Lua objects
- body, body_end_check = decode(body_rpos)
- assert(body_end == body_end_check, "invalid xrow length")
- if body and body[IPROTO_DATA_KEY] then
- request.response, request.errno =
- method_decoder[request.method](body[IPROTO_DATA_KEY])
- end
+ request.response, request.errno =
+ method_decoder[request.method](body_rpos, body_end)
request.cond:broadcast()
end
--
2.15.1 (Apple Git-101)
More information about the Tarantool-patches
mailing list