[Tarantool-patches] [PATCH v2] box: add binary search for _session_settings space
Chris Sosnin
k.sosnin at tarantool.org
Sun Jan 19 23:18:15 MSK 2020
Vlad, thank you for your suggestions!
Instead of using module_id as a flag, I added an explicit 'is_set' variable.
It is more convenient to use if you take into consideration adding more
modules. The rest is according to your advice: we set an interator with
binary search (finding lower/upper bound to be precise) and then do linear
lookup.
See the whole patch below:
As it is mentioned in implementation, it is important
that _session_settings options are sorted by name, so
there is no need in linear lookup and we can replace it
with binary search.
Closes #4712
---
branch: https://github.com/tarantool/tarantool/tree/ksosnin/gh-4712-search-settings
issue: https://github.com/tarantool/tarantool/issues/4712
src/box/session_settings.c | 92 ++++++++++++++++++++++++++++++++++++--
1 file changed, 88 insertions(+), 4 deletions(-)
diff --git a/src/box/session_settings.c b/src/box/session_settings.c
index a969d3d10..441dd29ff 100644
--- a/src/box/session_settings.c
+++ b/src/box/session_settings.c
@@ -74,6 +74,8 @@ struct session_settings_iterator {
bool is_eq;
/** True if the iterator should include equal keys. */
bool is_including;
+ /** True if the iterator is pointing to the existing setting */
+ bool is_set;
};
static void
@@ -85,6 +87,69 @@ session_settings_iterator_free(struct iterator *ptr)
free(it);
}
+static int
+session_settings_set_forward(const struct session_setting_module *module,
+ int *sid, const char *key, bool is_eq,
+ bool is_including)
+{
+ int count = module->setting_count;
+ int low = 0, high = count;
+ if (key == NULL)
+ return 0;
+ const char **name = module->settings;
+ while (low < high) {
+ int index = low + (high - low) / 2;
+ int cmp = strcmp(name[index], key);
+ if ((cmp < 0 && is_including) ||
+ (cmp <= 0 && !is_including))
+ low = index + 1;
+ else
+ high = index;
+ }
+ if (low < count) {
+ int cmp = strcmp(name[low], key);
+ if ((cmp == 0 && is_including) ||
+ (cmp > 0 && !is_eq)) {
+ *sid = low;
+ return 0;
+ }
+ }
+ *sid = count;
+ return -1;
+}
+
+static int
+session_settings_set_reverse(const struct session_setting_module *module,
+ int *sid, const char *key, bool is_eq,
+ bool is_including)
+{
+ int count = module->setting_count;
+ int low = -1, high = count - 1;
+ if (key == NULL)
+ return 0;
+ const char **name = module->settings;
+ while (low < high) {
+ int index = high - (high - low) / 2;
+ int cmp = strcmp(name[index], key);
+ if ((cmp > 0 && is_including) ||
+ (cmp >= 0 && !is_including))
+ high = index - 1;
+ else
+ low = index;
+ }
+ if (high >= 0) {
+ int cmp = strcmp(name[high], key);
+ if ((cmp == 0 && is_including) ||
+ (cmp < 0 && !is_eq)) {
+ *sid = high;
+ return 0;
+ }
+ }
+ *sid = count;
+ return -1;
+}
+
+
static int
session_settings_next_in_module(const struct session_setting_module *module,
int *sid, const char *key, bool is_eq,
@@ -148,6 +213,15 @@ session_settings_iterator_next(struct iterator *iterator, struct tuple **result)
bool is_found = false;
for (; mid < session_setting_type_MAX; ++mid, sid = 0) {
module = &session_setting_modules[mid];
+ if (!it->is_set) {
+ if (session_settings_set_forward(module, &sid, key,
+ is_eq,
+ is_including) == 0) {
+ it->is_set = true;
+ is_found = true;
+ break;
+ }
+ }
if (session_settings_next_in_module(module, &sid, key, is_eq,
is_including) == 0) {
is_found = true;
@@ -178,6 +252,15 @@ session_settings_iterator_prev(struct iterator *iterator, struct tuple **result)
bool is_found = false;
for (; mid >= 0; --mid, sid = INT_MAX) {
module = &session_setting_modules[mid];
+ if (!it->is_set) {
+ if (session_settings_set_reverse(module, &sid, key,
+ is_eq,
+ is_including) == 0) {
+ it->is_set = true;
+ is_found = true;
+ break;
+ }
+ }
if (session_settings_prev_in_module(module, &sid, key, is_eq,
is_including) == 0) {
is_found = true;
@@ -236,6 +319,7 @@ session_settings_index_create_iterator(struct index *base,
it->is_eq = type == ITER_EQ || type == ITER_REQ;
it->is_including = it->is_eq || type == ITER_GE || type == ITER_ALL ||
type == ITER_LE;
+ it->is_set = false;
it->format = index->format;
if (!iterator_type_is_reverse(type)) {
it->base.next = session_settings_iterator_next;
@@ -266,8 +350,8 @@ session_settings_index_get(struct index *base, const char *key,
struct session_setting_module *end = module + session_setting_type_MAX;
int sid = 0;
for (; module < end; ++module, sid = 0) {
- if (session_settings_next_in_module(module, &sid, key, true,
- true) == 0)
+ if (session_settings_set_forward(module, &sid, key, true,
+ true) == 0)
goto found;
}
*result = NULL;
@@ -373,8 +457,8 @@ session_settings_space_execute_update(struct space *space, struct txn *txn,
struct session_setting_module *module = &session_setting_modules[0];
struct session_setting_module *end = module + session_setting_type_MAX;
for (; module < end; ++module, sid = 0) {
- if (session_settings_next_in_module(module, &sid, key, true,
- true) == 0)
+ if (session_settings_set_forward(module, &sid, key, true,
+ true) == 0)
goto found;
}
*result = NULL;
--
2.21.0 (Apple Git-122.2)
More information about the Tarantool-patches
mailing list