From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Vladimir Davydov Subject: [PATCH 09/13] vinyl: forward tuple comparison hints to memory tree Date: Tue, 2 Apr 2019 20:33:46 +0300 Message-Id: <358d327ef53010318bb2baa0ced4c69280ab51af.1554225074.git.vdavydov.dev@gmail.com> In-Reply-To: References: In-Reply-To: References: To: kostja.osipov@gmail.com Cc: tarantool-patches@freelists.org List-ID: Instead of computing a statement comparison hint in a vy_mem method, forward it from the upper level, which already has it computed. Apart from eliminating extra calls to vy_stmt_hint, this is also a prerequisite for multikey indexes, which will reuse hints to store offsets of indexed array entries and thus make hints impossible to be computed in an arbitrary place in code. --- src/box/vinyl.c | 10 ++++++---- src/box/vy_lsm.c | 24 +++++++++++++----------- src/box/vy_lsm.h | 10 +++++++--- src/box/vy_mem.c | 12 ++++-------- src/box/vy_mem.h | 11 +++++++---- src/box/vy_tx.c | 16 ++++++++++------ test/unit/vy_iterators_helper.c | 5 +++-- test/unit/vy_mem.c | 13 ++++++++----- 8 files changed, 58 insertions(+), 43 deletions(-) diff --git a/src/box/vinyl.c b/src/box/vinyl.c index d8e22eb8..3e96f5f5 100644 --- a/src/box/vinyl.c +++ b/src/box/vinyl.c @@ -3583,7 +3583,7 @@ vy_squash_process(struct vy_squash *squash) */ size_t mem_used_before = lsregion_used(&env->mem_env.allocator); const struct tuple *region_stmt = NULL; - int rc = vy_lsm_set(lsm, mem, result, ®ion_stmt); + int rc = vy_lsm_set(lsm, mem, result, hint, ®ion_stmt); tuple_unref(result); size_t mem_used_after = lsregion_used(&env->mem_env.allocator); assert(mem_used_after >= mem_used_before); @@ -4006,12 +4006,13 @@ static int vy_build_insert_stmt(struct vy_lsm *lsm, struct vy_mem *mem, const struct tuple *stmt, int64_t lsn) { + hint_t hint = vy_stmt_hint(stmt, lsm->cmp_def); const struct tuple *region_stmt = vy_stmt_dup_lsregion(stmt, &mem->env->allocator, mem->generation); if (region_stmt == NULL) return -1; vy_stmt_set_lsn((struct tuple *)region_stmt, lsn); - if (vy_mem_insert(mem, region_stmt) != 0) + if (vy_mem_insert(mem, region_stmt, hint) != 0) return -1; vy_mem_commit_stmt(mem, region_stmt); vy_stmt_counter_acct_tuple(&lsm->stat.memory.count, region_stmt); @@ -4470,10 +4471,11 @@ vy_deferred_delete_on_replace(struct trigger *trigger, void *event) break; mem = lsm->mem; } - rc = vy_lsm_set(lsm, mem, delete, ®ion_stmt); + hint_t hint = vy_stmt_hint(delete, lsm->cmp_def); + rc = vy_lsm_set(lsm, mem, delete, hint, ®ion_stmt); if (rc != 0) break; - vy_lsm_commit_stmt(lsm, mem, region_stmt); + vy_lsm_commit_stmt(lsm, mem, region_stmt, hint); if (!is_first_statement) continue; diff --git a/src/box/vy_lsm.c b/src/box/vy_lsm.c index 52fd429d..4065f711 100644 --- a/src/box/vy_lsm.c +++ b/src/box/vy_lsm.c @@ -885,7 +885,8 @@ vy_lsm_delete_mem(struct vy_lsm *lsm, struct vy_mem *mem) int vy_lsm_set(struct vy_lsm *lsm, struct vy_mem *mem, - const struct tuple *stmt, const struct tuple **region_stmt) + const struct tuple *stmt, hint_t hint, + const struct tuple **region_stmt) { uint32_t format_id = stmt->format_id; @@ -917,9 +918,9 @@ vy_lsm_set(struct vy_lsm *lsm, struct vy_mem *mem, return -1; } if (vy_stmt_type(*region_stmt) != IPROTO_UPSERT) - return vy_mem_insert(mem, *region_stmt); + return vy_mem_insert(mem, *region_stmt, hint); else - return vy_mem_insert_upsert(mem, *region_stmt); + return vy_mem_insert_upsert(mem, *region_stmt, hint); } /** @@ -931,10 +932,11 @@ vy_lsm_set(struct vy_lsm *lsm, struct vy_mem *mem, * @param lsm LSM tree the statement was committed to. * @param mem In-memory tree where the statement was saved. * @param stmt UPSERT statement to squash. + * @param hint Statement comparison hint. */ static void vy_lsm_commit_upsert(struct vy_lsm *lsm, struct vy_mem *mem, - const struct tuple *stmt) + const struct tuple *stmt, hint_t hint) { assert(vy_stmt_type(stmt) == IPROTO_UPSERT); assert(vy_stmt_lsn(stmt) < MAX_LSN); @@ -971,7 +973,7 @@ vy_lsm_commit_upsert(struct vy_lsm *lsm, struct vy_mem *mem, * one-key continous UPSERTs sequence. */ #ifndef NDEBUG - older = vy_mem_older_lsn(mem, stmt); + older = vy_mem_older_lsn(mem, stmt, hint); assert(older != NULL && vy_stmt_type(older) == IPROTO_UPSERT && vy_stmt_n_upserts(older) == VY_UPSERT_THRESHOLD - 1); #endif @@ -1000,7 +1002,7 @@ vy_lsm_commit_upsert(struct vy_lsm *lsm, struct vy_mem *mem, if (n_upserts == 0 && lsm->stat.memory.count.rows == lsm->mem->count.rows && lsm->run_count == 0) { - older = vy_mem_older_lsn(mem, stmt); + older = vy_mem_older_lsn(mem, stmt, hint); assert(older == NULL || vy_stmt_type(older) != IPROTO_UPSERT); struct tuple *upserted = vy_apply_upsert(stmt, older, lsm->cmp_def, false); @@ -1037,7 +1039,7 @@ vy_lsm_commit_upsert(struct vy_lsm *lsm, struct vy_mem *mem, return; } - int rc = vy_lsm_set(lsm, mem, upserted, ®ion_stmt); + int rc = vy_lsm_set(lsm, mem, upserted, hint, ®ion_stmt); /** * Since we have already allocated mem statement and * now we replacing one statement with another, the @@ -1052,14 +1054,14 @@ vy_lsm_commit_upsert(struct vy_lsm *lsm, struct vy_mem *mem, void vy_lsm_commit_stmt(struct vy_lsm *lsm, struct vy_mem *mem, - const struct tuple *stmt) + const struct tuple *stmt, hint_t hint) { vy_mem_commit_stmt(mem, stmt); lsm->stat.memory.count.rows++; if (vy_stmt_type(stmt) == IPROTO_UPSERT) - vy_lsm_commit_upsert(lsm, mem, stmt); + vy_lsm_commit_upsert(lsm, mem, stmt, hint); vy_stmt_counter_acct_tuple(&lsm->stat.put, stmt); @@ -1069,9 +1071,9 @@ vy_lsm_commit_stmt(struct vy_lsm *lsm, struct vy_mem *mem, void vy_lsm_rollback_stmt(struct vy_lsm *lsm, struct vy_mem *mem, - const struct tuple *stmt) + const struct tuple *stmt, hint_t hint) { - vy_mem_rollback_stmt(mem, stmt); + vy_mem_rollback_stmt(mem, stmt, hint); /* Invalidate cache element. */ vy_cache_on_write(&lsm->cache, stmt, NULL); diff --git a/src/box/vy_lsm.h b/src/box/vy_lsm.h index c85bd2b3..541c49f8 100644 --- a/src/box/vy_lsm.h +++ b/src/box/vy_lsm.h @@ -590,6 +590,7 @@ vy_lsm_force_compaction(struct vy_lsm *lsm); * @param lsm LSM tree the statement is for. * @param mem In-memory tree to insert the statement into. * @param stmt Statement, allocated on malloc(). + * @param hint Statement comparison hint. * @param region_stmt NULL or the same statement, allocated on * lsregion. * @@ -598,7 +599,8 @@ vy_lsm_force_compaction(struct vy_lsm *lsm); */ int vy_lsm_set(struct vy_lsm *lsm, struct vy_mem *mem, - const struct tuple *stmt, const struct tuple **region_stmt); + const struct tuple *stmt, hint_t hint, + const struct tuple **region_stmt); /** * Confirm that the statement stays in the in-memory index of @@ -607,10 +609,11 @@ vy_lsm_set(struct vy_lsm *lsm, struct vy_mem *mem, * @param lsm LSM tree the statement is for. * @param mem In-memory tree where the statement was saved. * @param stmt Statement allocated from lsregion. + * @param hint Statement comparison hint. */ void vy_lsm_commit_stmt(struct vy_lsm *lsm, struct vy_mem *mem, - const struct tuple *stmt); + const struct tuple *stmt, hint_t hint); /** * Erase a statement from the in-memory index of an LSM tree. @@ -618,10 +621,11 @@ vy_lsm_commit_stmt(struct vy_lsm *lsm, struct vy_mem *mem, * @param lsm LSM tree to erase from. * @param mem In-memory tree where the statement was saved. * @param stmt Statement allocated from lsregion. + * @param hint Statement comparison hint. */ void vy_lsm_rollback_stmt(struct vy_lsm *lsm, struct vy_mem *mem, - const struct tuple *stmt); + const struct tuple *stmt, hint_t hint); #if defined(__cplusplus) } /* extern "C" */ diff --git a/src/box/vy_mem.c b/src/box/vy_mem.c index 87ad0661..4947df2a 100644 --- a/src/box/vy_mem.c +++ b/src/box/vy_mem.c @@ -149,9 +149,8 @@ vy_mem_delete(struct vy_mem *index) } const struct tuple * -vy_mem_older_lsn(struct vy_mem *mem, const struct tuple *stmt) +vy_mem_older_lsn(struct vy_mem *mem, const struct tuple *stmt, hint_t hint) { - hint_t hint = vy_stmt_hint(stmt, mem->cmp_def); struct vy_mem_tree_key tree_key = vy_mem_tree_key(stmt, hint, vy_stmt_lsn(stmt) - 1); bool exact = false; @@ -170,14 +169,13 @@ vy_mem_older_lsn(struct vy_mem *mem, const struct tuple *stmt) } int -vy_mem_insert_upsert(struct vy_mem *mem, const struct tuple *stmt) +vy_mem_insert_upsert(struct vy_mem *mem, const struct tuple *stmt, hint_t hint) { assert(vy_stmt_type(stmt) == IPROTO_UPSERT); /* Check if the statement can be inserted in the vy_mem. */ assert(stmt->format_id == tuple_format_id(mem->format)); /* The statement must be from a lsregion. */ assert(!vy_stmt_is_refable(stmt)); - hint_t hint = vy_stmt_hint(stmt, mem->cmp_def); size_t size = tuple_size(stmt); struct vy_mem_tree_elem new = vy_mem_tree_elem(stmt, hint); struct vy_mem_tree_elem replaced = vy_mem_tree_elem_invalid(); @@ -233,7 +231,7 @@ vy_mem_insert_upsert(struct vy_mem *mem, const struct tuple *stmt) } int -vy_mem_insert(struct vy_mem *mem, const struct tuple *stmt) +vy_mem_insert(struct vy_mem *mem, const struct tuple *stmt, hint_t hint) { assert(vy_stmt_type(stmt) != IPROTO_UPSERT); /* Check if the statement can be inserted in the vy_mem. */ @@ -241,7 +239,6 @@ vy_mem_insert(struct vy_mem *mem, const struct tuple *stmt) stmt->format_id == tuple_format_id(mem->format)); /* The statement must be from a lsregion. */ assert(!vy_stmt_is_refable(stmt)); - hint_t hint = vy_stmt_hint(stmt, mem->cmp_def); size_t size = tuple_size(stmt); struct vy_mem_tree_elem new = vy_mem_tree_elem(stmt, hint); struct vy_mem_tree_elem replaced = vy_mem_tree_elem_invalid(); @@ -281,11 +278,10 @@ vy_mem_commit_stmt(struct vy_mem *mem, const struct tuple *stmt) } void -vy_mem_rollback_stmt(struct vy_mem *mem, const struct tuple *stmt) +vy_mem_rollback_stmt(struct vy_mem *mem, const struct tuple *stmt, hint_t hint) { /* This is the statement we've inserted before. */ assert(!vy_stmt_is_refable(stmt)); - hint_t hint = vy_stmt_hint(stmt, mem->cmp_def); struct vy_mem_tree_elem elem = vy_mem_tree_elem(stmt, hint); int rc = vy_mem_tree_delete(&mem->tree, elem); assert(rc == 0); diff --git a/src/box/vy_mem.h b/src/box/vy_mem.h index f31deaed..360e1d9c 100644 --- a/src/box/vy_mem.h +++ b/src/box/vy_mem.h @@ -309,30 +309,32 @@ vy_mem_delete(struct vy_mem *index); * Return the older statement for the given one. */ const struct tuple * -vy_mem_older_lsn(struct vy_mem *mem, const struct tuple *stmt); +vy_mem_older_lsn(struct vy_mem *mem, const struct tuple *stmt, hint_t hint); /** * Insert a statement into the in-memory level. * @param mem vy_mem. * @param stmt Vinyl statement. + * @param hint Statement comparison hint. * * @retval 0 Success. * @retval -1 Memory error. */ int -vy_mem_insert(struct vy_mem *mem, const struct tuple *stmt); +vy_mem_insert(struct vy_mem *mem, const struct tuple *stmt, hint_t hint); /** * Insert an upsert statement into the mem. * * @param mem Mem to insert to. * @param stmt Upsert statement to insert. + * @param hint Statement comparison hint. * * @retval 0 Success. * @retval -1 Memory error. */ int -vy_mem_insert_upsert(struct vy_mem *mem, const struct tuple *stmt); +vy_mem_insert_upsert(struct vy_mem *mem, const struct tuple *stmt, hint_t hint); /** * Confirm insertion of a statement into the in-memory level. @@ -346,9 +348,10 @@ vy_mem_commit_stmt(struct vy_mem *mem, const struct tuple *stmt); * Remove a statement from the in-memory level. * @param mem vy_mem. * @param stmt Vinyl statement. + * @param hint Statement comparison hint. */ void -vy_mem_rollback_stmt(struct vy_mem *mem, const struct tuple *stmt); +vy_mem_rollback_stmt(struct vy_mem *mem, const struct tuple *stmt, hint_t hint); /** * Iterator for in-memory level. diff --git a/src/box/vy_tx.c b/src/box/vy_tx.c index d8d7c905..fd8822a1 100644 --- a/src/box/vy_tx.c +++ b/src/box/vy_tx.c @@ -490,6 +490,7 @@ vy_tx_write_prepare(struct txv *v) * @param lsm LSM tree to write to. * @param mem In-memory tree to write to. * @param stmt Statement allocated with malloc(). + * @param hint Statement comparison hint. * @param region_stmt NULL or the same statement as stmt, * but allocated on lsregion. * @@ -498,7 +499,8 @@ vy_tx_write_prepare(struct txv *v) */ static int vy_tx_write(struct vy_lsm *lsm, struct vy_mem *mem, - struct tuple *stmt, const struct tuple **region_stmt) + struct tuple *stmt, hint_t hint, + const struct tuple **region_stmt) { assert(vy_stmt_is_refable(stmt)); assert(*region_stmt == NULL || !vy_stmt_is_refable(*region_stmt)); @@ -520,7 +522,7 @@ vy_tx_write(struct vy_lsm *lsm, struct vy_mem *mem, tuple_unref(deleted); if (applied != NULL) { assert(vy_stmt_type(applied) == IPROTO_REPLACE); - int rc = vy_lsm_set(lsm, mem, applied, + int rc = vy_lsm_set(lsm, mem, applied, hint, region_stmt); tuple_unref(applied); return rc; @@ -534,7 +536,7 @@ vy_tx_write(struct vy_lsm *lsm, struct vy_mem *mem, /* Invalidate cache element. */ vy_cache_on_write(&lsm->cache, stmt, NULL); } - return vy_lsm_set(lsm, mem, stmt, region_stmt); + return vy_lsm_set(lsm, mem, stmt, hint, region_stmt); } /** @@ -775,7 +777,8 @@ vy_tx_prepare(struct vy_tx *tx) vy_stmt_set_lsn(v->stmt, MAX_LSN + tx->psn); const struct tuple **region_stmt = (type == IPROTO_DELETE) ? &delete : &repsert; - if (vy_tx_write(lsm, v->mem, v->stmt, region_stmt) != 0) + if (vy_tx_write(lsm, v->mem, v->stmt, v->hint, + region_stmt) != 0) return -1; v->region_stmt = *region_stmt; } @@ -805,7 +808,8 @@ vy_tx_commit(struct vy_tx *tx, int64_t lsn) stailq_foreach_entry(v, &tx->log, next_in_log) { if (v->region_stmt != NULL) { vy_stmt_set_lsn((struct tuple *)v->region_stmt, lsn); - vy_lsm_commit_stmt(v->lsm, v->mem, v->region_stmt); + vy_lsm_commit_stmt(v->lsm, v->mem, + v->region_stmt, v->hint); } if (v->mem != NULL) vy_mem_unpin(v->mem); @@ -851,7 +855,7 @@ vy_tx_rollback_after_prepare(struct vy_tx *tx) stailq_foreach_entry(v, &tx->log, next_in_log) { if (v->region_stmt != NULL) vy_lsm_rollback_stmt(v->lsm, v->mem, - v->region_stmt); + v->region_stmt, v->hint); if (v->mem != NULL) vy_mem_unpin(v->mem); } diff --git a/test/unit/vy_iterators_helper.c b/test/unit/vy_iterators_helper.c index 173d58db..d2ac21a0 100644 --- a/test/unit/vy_iterators_helper.c +++ b/test/unit/vy_iterators_helper.c @@ -136,12 +136,13 @@ vy_mem_insert_template(struct vy_mem *mem, const struct vy_stmt_template *templ) struct tuple *stmt = vy_new_simple_stmt(mem->format, templ); struct tuple *region_stmt = vy_stmt_dup_lsregion(stmt, &mem->env->allocator, mem->generation); + hint_t hint = vy_stmt_hint(stmt, mem->cmp_def); assert(region_stmt != NULL); tuple_unref(stmt); if (templ->type == IPROTO_UPSERT) - vy_mem_insert_upsert(mem, region_stmt); + vy_mem_insert_upsert(mem, region_stmt, hint); else - vy_mem_insert(mem, region_stmt); + vy_mem_insert(mem, region_stmt, hint); return region_stmt; } diff --git a/test/unit/vy_mem.c b/test/unit/vy_mem.c index 4453e076..0355653a 100644 --- a/test/unit/vy_mem.c +++ b/test/unit/vy_mem.c @@ -27,6 +27,7 @@ test_basic(void) /* Check dump lsn */ const struct tuple *stmt = vy_mem_insert_template(mem, &stmts[0]); + hint_t hint = vy_stmt_hint(stmt, key_def); is(mem->dump_lsn, -1, "mem->dump_lsn after prepare"); vy_mem_commit_stmt(mem, stmt); is(mem->dump_lsn, 100, "mem->dump_lsn after commit"); @@ -34,17 +35,19 @@ test_basic(void) /* Check vy_mem_older_lsn */ const struct tuple *older = stmt; stmt = vy_mem_insert_template(mem, &stmts[1]); - is(vy_mem_older_lsn(mem, stmt), older, "vy_mem_older_lsn 1"); - is(vy_mem_older_lsn(mem, older), NULL, "vy_mem_older_lsn 2"); + hint = vy_stmt_hint(stmt, key_def); + is(vy_mem_older_lsn(mem, stmt, hint), older, "vy_mem_older_lsn 1"); + is(vy_mem_older_lsn(mem, older, hint), NULL, "vy_mem_older_lsn 2"); vy_mem_commit_stmt(mem, stmt); /* Check rollback */ const struct tuple *olderolder = stmt; older = vy_mem_insert_template(mem, &stmts[2]); stmt = vy_mem_insert_template(mem, &stmts[3]); - is(vy_mem_older_lsn(mem, stmt), older, "vy_mem_rollback 1"); - vy_mem_rollback_stmt(mem, older); - is(vy_mem_older_lsn(mem, stmt), olderolder, "vy_mem_rollback 2"); + hint = vy_stmt_hint(stmt, key_def); + is(vy_mem_older_lsn(mem, stmt, hint), older, "vy_mem_rollback 1"); + vy_mem_rollback_stmt(mem, older, hint); + is(vy_mem_older_lsn(mem, stmt, hint), olderolder, "vy_mem_rollback 2"); /* Check version */ stmt = vy_mem_insert_template(mem, &stmts[4]); -- 2.11.0