From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Subject: Re: [tarantool-patches] Re: [PATCH v6 1/3] box: refactor key_def_set_compare_func routine References: <34cf8ed7af4b1da74a89a260562abe08526cd4e8.1552478226.git.kshcherbatov@tarantool.org> <20190314070447.dpdu3aocinfiwrtr@esperanza> From: Kirill Shcherbatov Message-ID: <9b725e11-1fe7-6cad-d810-5181056cde9d@tarantool.org> Date: Fri, 15 Mar 2019 13:20:11 +0300 MIME-Version: 1.0 In-Reply-To: <20190314070447.dpdu3aocinfiwrtr@esperanza> Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit To: tarantool-patches@freelists.org, Vladimir Davydov List-ID: Refactored key_def_set_compare_func routine to make it easier to read, maintain, and extend. This is necessary due to the fact that in a series of subsequent patches it will be significantly expanded. Needed for #3961 --- src/box/tuple_compare.cc | 195 +++++++++++++++++++-------------------- 1 file changed, 93 insertions(+), 102 deletions(-) diff --git a/src/box/tuple_compare.cc b/src/box/tuple_compare.cc index dfe30b190..7fe1766a8 100644 --- a/src/box/tuple_compare.cc +++ b/src/box/tuple_compare.cc @@ -986,7 +986,7 @@ struct comparator_signature { /** * field1 no, field1 type, field2 no, field2 type, ... */ -static const comparator_signature cmp_arr[] = { +static const comparator_signature precompiled_cmp_arr[] = { COMPARATOR(0, FIELD_TYPE_UNSIGNED) COMPARATOR(0, FIELD_TYPE_STRING) COMPARATOR(0, FIELD_TYPE_UNSIGNED, 1, FIELD_TYPE_UNSIGNED) @@ -1005,55 +1005,6 @@ static const comparator_signature cmp_arr[] = { #undef COMPARATOR -static const tuple_compare_t compare_slowpath_funcs[] = { - tuple_compare_slowpath, - tuple_compare_slowpath, - tuple_compare_slowpath, - tuple_compare_slowpath, - tuple_compare_slowpath, - tuple_compare_slowpath, - tuple_compare_slowpath, - tuple_compare_slowpath -}; - -static tuple_compare_t -tuple_compare_create(const struct key_def *def) -{ - int cmp_func_idx = (def->is_nullable ? 1 : 0) + - 2 * (def->has_optional_parts ? 1 : 0) + - 4 * (def->has_json_paths ? 1 : 0); - if (def->is_nullable) { - if (key_def_is_sequential(def)) { - if (def->has_optional_parts) - return tuple_compare_sequential; - else - return tuple_compare_sequential; - } else { - return compare_slowpath_funcs[cmp_func_idx]; - } - } - assert(! def->has_optional_parts); - if (!key_def_has_collation(def) && !def->has_json_paths) { - /* Precalculated comparators don't use collation */ - for (uint32_t k = 0; - k < sizeof(cmp_arr) / sizeof(cmp_arr[0]); k++) { - uint32_t i = 0; - for (; i < def->part_count; i++) - if (def->parts[i].fieldno != - cmp_arr[k].p[i * 2] || - def->parts[i].type != - cmp_arr[k].p[i * 2 + 1]) - break; - if (i == def->part_count && - cmp_arr[k].p[i * 2] == UINT32_MAX) - return cmp_arr[k].f; - } - } - return key_def_is_sequential(def) ? - tuple_compare_sequential : - compare_slowpath_funcs[cmp_func_idx]; -} - /* }}} tuple_compare */ /* {{{ tuple_compare_with_key */ @@ -1215,7 +1166,7 @@ struct comparator_with_key_signature #define KEY_COMPARATOR(...) \ { TupleCompareWithKey<0, __VA_ARGS__>::compare, { __VA_ARGS__ } }, -static const comparator_with_key_signature cmp_wk_arr[] = { +static const comparator_with_key_signature precompiled_cmp_wk_arr[] = { KEY_COMPARATOR(0, FIELD_TYPE_UNSIGNED, 1, FIELD_TYPE_UNSIGNED, 2, FIELD_TYPE_UNSIGNED) KEY_COMPARATOR(0, FIELD_TYPE_STRING , 1, FIELD_TYPE_UNSIGNED, 2, FIELD_TYPE_UNSIGNED) KEY_COMPARATOR(0, FIELD_TYPE_UNSIGNED, 1, FIELD_TYPE_STRING , 2, FIELD_TYPE_UNSIGNED) @@ -1231,68 +1182,108 @@ static const comparator_with_key_signature cmp_wk_arr[] = { KEY_COMPARATOR(1, FIELD_TYPE_STRING , 2, FIELD_TYPE_STRING) }; -#undef KEY_COMPARATOR - -static const tuple_compare_with_key_t compare_with_key_slowpath_funcs[] = { - tuple_compare_with_key_slowpath, - tuple_compare_with_key_slowpath, - tuple_compare_with_key_slowpath, - tuple_compare_with_key_slowpath, - tuple_compare_with_key_slowpath, - tuple_compare_with_key_slowpath, - tuple_compare_with_key_slowpath, - tuple_compare_with_key_slowpath +#undef KEY_COMPARATORq + +#define COMPARE_SLOWPATH(...) \ + {tuple_compare_slowpath<__VA_ARGS__>, \ + tuple_compare_with_key_slowpath<__VA_ARGS__>, \ + __VA_ARGS__, false} + +#define COMPARE_SEQUENTIAL(...) \ + {tuple_compare_sequential<__VA_ARGS__>, \ + tuple_compare_with_key_sequential<__VA_ARGS__>, \ + __VA_ARGS__, false, true} + +static struct { + tuple_compare_t tuple_compare; + tuple_compare_with_key_t tuple_compare_with_key; + bool is_nullable; + bool has_optional_parts; + bool has_json_paths; + bool is_sequential; +} cmp_arr[] = { + COMPARE_SLOWPATH(false, false, false), + COMPARE_SLOWPATH(true, false, false), + COMPARE_SLOWPATH(false, true, false), + COMPARE_SLOWPATH(true, true, false), + COMPARE_SLOWPATH(false, false, true), + COMPARE_SLOWPATH(true, false, true), + COMPARE_SLOWPATH(false, true, true), + COMPARE_SLOWPATH(true, true, true), + COMPARE_SEQUENTIAL(false, false), + COMPARE_SEQUENTIAL(true, false), + COMPARE_SEQUENTIAL(false, true), + COMPARE_SEQUENTIAL(true, true), }; -static tuple_compare_with_key_t -tuple_compare_with_key_create(const struct key_def *def) +#undef COMPARE_SLOWPATH +#undef COMPARE_SEQUENTIAL + +/* }}} tuple_compare_with_key */ + +void +key_def_set_compare_func(struct key_def *def) { - int cmp_func_idx = (def->is_nullable ? 1 : 0) + - 2 * (def->has_optional_parts ? 1 : 0) + - 4 * (def->has_json_paths ? 1 : 0); - if (def->is_nullable) { - if (key_def_is_sequential(def)) { - if (def->has_optional_parts) { - return tuple_compare_with_key_sequential; - } else { - return tuple_compare_with_key_sequential; + def->tuple_compare = NULL; + def->tuple_compare_with_key = NULL; + if (!def->is_nullable && !key_def_has_collation(def) && + !def->has_json_paths) { + /* Precalculated comparators don't use collation */ + for (uint32_t k = 0; k < sizeof(precompiled_cmp_arr) / + sizeof(precompiled_cmp_arr[0]); k++) { + uint32_t i = 0; + for (; i < def->part_count; i++) { + if (def->parts[i].fieldno != + precompiled_cmp_arr[k].p[i * 2] || + def->parts[i].type != + precompiled_cmp_arr[k].p[i * 2 + 1]) + break; + } + if (i == def->part_count && + precompiled_cmp_arr[k].p[i * 2] == UINT32_MAX) { + def->tuple_compare = precompiled_cmp_arr[k].f; + break; } - } else { - return compare_with_key_slowpath_funcs[cmp_func_idx]; } - } - assert(! def->has_optional_parts); - if (!key_def_has_collation(def) && !def->has_json_paths) { - /* Precalculated comparators don't use collation */ - for (uint32_t k = 0; - k < sizeof(cmp_wk_arr) / sizeof(cmp_wk_arr[0]); - k++) { - + for (uint32_t k = 0; k < sizeof(precompiled_cmp_wk_arr) / + sizeof(precompiled_cmp_wk_arr[0]); k++) { uint32_t i = 0; for (; i < def->part_count; i++) { if (def->parts[i].fieldno != - cmp_wk_arr[k].p[i * 2] || - def->parts[i].type != - cmp_wk_arr[k].p[i * 2 + 1]) { + precompiled_cmp_wk_arr[k].p[i * 2] || + def->parts[i].type != + precompiled_cmp_wk_arr[k].p[i * 2 + 1]) break; + } + if (i == def->part_count) { + def->tuple_compare_with_key = + precompiled_cmp_wk_arr[k].f; + break; + } + } + } + if (def->tuple_compare == NULL || def->tuple_compare_with_key == NULL) { + for (uint32_t k = 0; k < sizeof(cmp_arr) / + sizeof(cmp_arr[0]); k++) { + if (def->is_nullable == cmp_arr[k].is_nullable && + def->has_optional_parts == + cmp_arr[k].has_optional_parts && + def->has_json_paths == cmp_arr[k].has_json_paths && + key_def_is_sequential(def) == + cmp_arr[k].is_sequential) { + if (def->tuple_compare == NULL) { + def->tuple_compare = + cmp_arr[k].tuple_compare; } + if (def->tuple_compare_with_key == NULL) { + def->tuple_compare_with_key = + cmp_arr[k]. + tuple_compare_with_key; + } + break; } - if (i == def->part_count) - return cmp_wk_arr[k].f; } } - return key_def_is_sequential(def) ? - tuple_compare_with_key_sequential : - compare_with_key_slowpath_funcs[cmp_func_idx]; -} - -/* }}} tuple_compare_with_key */ - -void -key_def_set_compare_func(struct key_def *def) -{ - def->tuple_compare = tuple_compare_create(def); - def->tuple_compare_with_key = tuple_compare_with_key_create(def); + assert(def->tuple_compare != NULL && + def->tuple_compare_with_key != NULL); } -- 2.21.0