diff --git a/CHANGELOG.md b/CHANGELOG.md index 18e7157a..9819b86e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +### Fixed +* drop wrap_box_space_func_result to cut allocations and speed up storage calls. + ## [1.6.1] - 19-09-25 ### Added diff --git a/crud/borders.lua b/crud/borders.lua index 96f70fa3..67347b8a 100644 --- a/crud/borders.lua +++ b/crud/borders.lua @@ -32,15 +32,11 @@ local function get_border_on_storage(border_name, space_name, index_id, field_na return nil, BorderError:new("Index %q of space doesn't exist", index_id, space_name) end - local function get_index_border(index) - return index[border_name](index) - end - - return schema.wrap_func_result(space, get_index_border, {index}, { + return schema.wrap_func_result(space, index[border_name], { add_space_schema_hash = true, field_names = field_names, fetch_latest_metadata = fetch_latest_metadata, - }) + }, index) end borders.storage_api = {[STAT_FUNC_NAME] = get_border_on_storage} diff --git a/crud/common/schema.lua b/crud/common/schema.lua index 4a2c3c37..7a392201 100644 --- a/crud/common/schema.lua +++ b/crud/common/schema.lua @@ -209,14 +209,16 @@ function schema.truncate_row_trailing_fields(tuple, field_names) return tuple end -function schema.wrap_func_result(space, func, args, opts) - dev_checks('table', 'function', 'table', 'table') - +-- schema.wrap_func_result pcalls function +-- and returns its result as a table +-- `{res = ..., err = ..., space_schema_hash = ...}` +-- space_schema_hash is computed if function failed and +-- `add_space_schema_hash` is true +function schema.wrap_func_result(space, func, opts, ...) + dev_checks('table', 'function', 'table') local result = {} - opts = opts or {} - - local ok, func_res = pcall(func, unpack(args)) + local ok, func_res = pcall(func, ...) if ok then if opts.noreturn ~= true then result.res = filter_tuple_fields(func_res, opts.field_names) @@ -246,20 +248,6 @@ function schema.wrap_func_result(space, func, args, opts) return result end --- schema.wrap_box_space_func_result pcalls some box.space function --- and returns its result as a table --- `{res = ..., err = ..., space_schema_hash = ...}` --- space_schema_hash is computed if function failed and --- `add_space_schema_hash` is true -function schema.wrap_box_space_func_result(space, box_space_func_name, box_space_func_args, opts) - dev_checks('table', 'string', 'table', 'table') - local function func(space, box_space_func_name, box_space_func_args) - return space[box_space_func_name](space, unpack(box_space_func_args)) - end - - return schema.wrap_func_result(space, func, {space, box_space_func_name, box_space_func_args}, opts) -end - -- schema.result_needs_reload checks that schema reload can -- be helpful to avoid storage error. -- It checks if space_schema_hash returned by storage diff --git a/crud/delete.lua b/crud/delete.lua index 6f15b9af..8cb5c412 100644 --- a/crud/delete.lua +++ b/crud/delete.lua @@ -44,12 +44,12 @@ local function delete_on_storage(space_name, key, field_names, opts) -- add_space_schema_hash is false because -- reloading space format on router can't avoid delete error on storage - return schema.wrap_box_space_func_result(space, 'delete', {key}, { + return schema.wrap_func_result(space, space.delete, { add_space_schema_hash = false, field_names = field_names, noreturn = opts.noreturn, fetch_latest_metadata = opts.fetch_latest_metadata, - }) + }, space, key) end delete.storage_api = {[DELETE_FUNC_NAME] = delete_on_storage} diff --git a/crud/get.lua b/crud/get.lua index feca57c5..8ddeca3d 100644 --- a/crud/get.lua +++ b/crud/get.lua @@ -43,11 +43,11 @@ local function get_on_storage(space_name, key, field_names, opts) -- add_space_schema_hash is false because -- reloading space format on router can't avoid get error on storage - return schema.wrap_box_space_func_result(space, 'get', {key}, { + return schema.wrap_func_result(space, space.get, { add_space_schema_hash = false, field_names = field_names, fetch_latest_metadata = opts.fetch_latest_metadata, - }) + }, space, key) end get.storage_api = {[GET_FUNC_NAME] = get_on_storage} diff --git a/crud/insert.lua b/crud/insert.lua index ebb3f865..11288b5f 100644 --- a/crud/insert.lua +++ b/crud/insert.lua @@ -45,12 +45,12 @@ local function insert_on_storage(space_name, tuple, opts) -- add_space_schema_hash is true only in case of insert_object -- the only one case when reloading schema can avoid insert error -- is flattening object on router - return schema.wrap_box_space_func_result(space, 'insert', {tuple}, { + return schema.wrap_func_result(space, space.insert, { add_space_schema_hash = opts.add_space_schema_hash, field_names = opts.fields, noreturn = opts.noreturn, fetch_latest_metadata = opts.fetch_latest_metadata, - }) + }, space, tuple) end insert.storage_api = {[INSERT_FUNC_NAME] = insert_on_storage} diff --git a/crud/insert_many.lua b/crud/insert_many.lua index f4299fd6..614ff5a7 100644 --- a/crud/insert_many.lua +++ b/crud/insert_many.lua @@ -52,17 +52,22 @@ local function insert_many_on_storage(space_name, tuples, opts) local errs = {} local replica_schema_version = nil + local insert_opts = { + add_space_schema_hash = opts.add_space_schema_hash, + field_names = opts.fields, + noreturn = opts.noreturn, + fetch_latest_metadata = opts.fetch_latest_metadata, + } + box.begin() for i, tuple in ipairs(tuples) do -- add_space_schema_hash is true only in case of insert_object_many -- the only one case when reloading schema can avoid insert error -- is flattening object on router - local insert_result = schema.wrap_box_space_func_result(space, 'insert', {tuple}, { - add_space_schema_hash = opts.add_space_schema_hash, - field_names = opts.fields, - noreturn = opts.noreturn, - fetch_latest_metadata = opts.fetch_latest_metadata, - }) + local insert_result = schema.wrap_func_result( + space, space.insert, insert_opts, + space, tuple + ) if opts.fetch_latest_metadata then replica_schema_version = insert_result.storage_info.replica_schema_version end diff --git a/crud/replace.lua b/crud/replace.lua index 5e36906f..d2999d58 100644 --- a/crud/replace.lua +++ b/crud/replace.lua @@ -45,12 +45,14 @@ local function replace_on_storage(space_name, tuple, opts) -- add_space_schema_hash is true only in case of replace_object -- the only one case when reloading schema can avoid insert error -- is flattening object on router - return schema.wrap_box_space_func_result(space, 'replace', {tuple}, { + + local result = schema.wrap_func_result(space, space.replace, { add_space_schema_hash = opts.add_space_schema_hash, field_names = opts.fields, noreturn = opts.noreturn, fetch_latest_metadata = opts.fetch_latest_metadata, - }) + }, space, tuple) + return result end replace.storage_api = {[REPLACE_FUNC_NAME] = replace_on_storage} diff --git a/crud/replace_many.lua b/crud/replace_many.lua index d047a3b0..59e10bba 100644 --- a/crud/replace_many.lua +++ b/crud/replace_many.lua @@ -52,17 +52,22 @@ local function replace_many_on_storage(space_name, tuples, opts) local errs = {} local replica_schema_version = nil + local replace_opts = { + add_space_schema_hash = opts.add_space_schema_hash, + field_names = opts.fields, + noreturn = opts.noreturn, + fetch_latest_metadata = opts.fetch_latest_metadata, + } + box.begin() for i, tuple in ipairs(tuples) do -- add_space_schema_hash is true only in case of replace_object_many -- the only one case when reloading schema can avoid replace error -- is flattening object on router - local insert_result = schema.wrap_box_space_func_result(space, 'replace', {tuple}, { - add_space_schema_hash = opts.add_space_schema_hash, - field_names = opts.fields, - noreturn = opts.noreturn, - fetch_latest_metadata = opts.fetch_latest_metadata, - }) + local insert_result = schema.wrap_func_result( + space, space.replace, replace_opts, + space, tuple + ) if opts.fetch_latest_metadata then replica_schema_version = insert_result.storage_info.replica_schema_version diff --git a/crud/update.lua b/crud/update.lua index 36ce242d..74a1fbc6 100644 --- a/crud/update.lua +++ b/crud/update.lua @@ -44,12 +44,12 @@ local function update_on_storage(space_name, key, operations, field_names, opts) -- add_space_schema_hash is false because -- reloading space format on router can't avoid update error on storage - local res, err = schema.wrap_box_space_func_result(space, 'update', {key, operations}, { + local res, err = schema.wrap_func_result(space, space.update, { add_space_schema_hash = false, field_names = field_names, noreturn = opts.noreturn, fetch_latest_metadata = opts.fetch_latest_metadata, - }) + }, space, key, operations) if err ~= nil then return nil, err @@ -66,12 +66,12 @@ local function update_on_storage(space_name, key, operations, field_names, opts) -- More details: https://github.com/tarantool/tarantool/issues/3378 if utils.is_field_not_found(res.err.code) then operations = utils.add_intermediate_nullable_fields(operations, space:format(), space:get(key)) - res, err = schema.wrap_box_space_func_result(space, 'update', {key, operations}, { + res, err = schema.wrap_func_result(space, space.update, { add_space_schema_hash = false, field_names = field_names, noreturn = opts.noreturn, fetch_latest_metadata = opts.fetch_latest_metadata, - }) + }, space, key, operations) end return res, err diff --git a/crud/upsert.lua b/crud/upsert.lua index 5be7bc4a..09fdadbd 100644 --- a/crud/upsert.lua +++ b/crud/upsert.lua @@ -44,10 +44,10 @@ local function upsert_on_storage(space_name, tuple, operations, opts) -- add_space_schema_hash is true only in case of upsert_object -- the only one case when reloading schema can avoid insert error -- is flattening object on router - return schema.wrap_box_space_func_result(space, 'upsert', {tuple, operations}, { + return schema.wrap_func_result(space, space.upsert, { add_space_schema_hash = opts.add_space_schema_hash, fetch_latest_metadata = opts.fetch_latest_metadata, - }) + }, space, tuple, operations) end upsert.storage_api = {[UPSERT_FUNC_NAME] = upsert_on_storage} diff --git a/crud/upsert_many.lua b/crud/upsert_many.lua index f030e778..60adea5a 100644 --- a/crud/upsert_many.lua +++ b/crud/upsert_many.lua @@ -51,15 +51,20 @@ local function upsert_many_on_storage(space_name, tuples, operations, opts) local errs = {} local replica_schema_version = nil + local upsert_opts = { + add_space_schema_hash = opts.add_space_schema_hash, + fetch_latest_metadata = opts.fetch_latest_metadata, + } + box.begin() for i, tuple in ipairs(tuples) do -- add_space_schema_hash is true only in case of upsert_object_many -- the only one case when reloading schema can avoid upsert error -- is flattening object on router - local insert_result = schema.wrap_box_space_func_result(space, 'upsert', {tuple, operations[i]}, { - add_space_schema_hash = opts.add_space_schema_hash, - fetch_latest_metadata = opts.fetch_latest_metadata, - }) + local insert_result = schema.wrap_func_result( + space, space.upsert, upsert_opts, space, + tuple, operations[i] + ) if opts.fetch_latest_metadata then replica_schema_version = insert_result.storage_info.replica_schema_version end