From: "n.pettik" <korablev@tarantool.org> To: tarantool-patches@freelists.org Cc: Vladislav Shpilevoy <v.shpilevoy@tarantool.org> Subject: [tarantool-patches] Re: [PATCH] sql: remove redundant goto from VDBE prologue Date: Mon, 18 Jun 2018 13:46:04 +0300 [thread overview] Message-ID: <28322F56-E52D-42C7-AE52-188D6F50AF63@tarantool.org> (raw) In-Reply-To: <24a1a33e-02cc-ccf4-7ff9-a155f5e18781@tarantool.org> > 1. This function looks small. Lets refactor it to Tarantool > code style. If we don't, I am afraid this commit will be lost > in 'git blame', when this function finally will be refactored > completely. > Ok. See diff at the end of letter. >> sqlite3VdbeJumpHere(v, 0); >> if (pParse->initiateTTrans) >> sqlite3VdbeAddOp0(v, OP_TTransaction); >> - if (db->init.busy == 0) >> - sqlite3VdbeChangeP5(v, 1); > > 2. Why is it removed? I do not see this code moved below. Actually, this code looks strange. If OP_TTransaction is added, then setting fifth param for it makes no sense (this opcode takes no args). If this change is related to OP_Halt, then it is also useless, since the last OP_Halt must be with signature 0 0 0 (comment from vdbe.c): * There is an implied "Halt 0 0 0" instruction inserted at the very end of * every program. So a jump past the last instruction of the program * is the same as executing Halt. That is why I removed this code. > >> - >> /* Code constant expressions that where factored out of inner loops */ >> if (pParse->pConstExpr) { >> ExprList *pEL = pParse->pConstExpr; >> @@ -107,10 +104,22 @@ sqlite3FinishCoding(Parse * pParse) >> iConstExprReg); >> } >> } >> - >> - /* Finally, jump back to the beginning of the executable code. */ >> - sqlite3VdbeGoto(v, 1); >> } >> + /* >> + * Finally, jump back to the beginning of >> + * the executable code. In fact, it is required >> + * only if some additional opcodes are generated. >> + * Otherwise, it would be useless jump: >> + * >> + * 0: OP_Init 0 vdbe_end ... >> + * 1: ... >> + * ... >> + * vdbe_end: OP_Goto 0 1 ... >> + */ >> + if (pParse->pConstExpr != NULL || pParse->initiateTTrans) >> + sqlite3VdbeGoto(v, 1); >> + else >> + sqlite3VdbeChangeP2(v, 0, 1); > > 3. As far as I see, P2 in OP_Init is 1 already when we are here. It is > not? See allocVdbe function. P2 == 1 by default, and here it can be changed to > goto to ttrans. In fact, it is changed by sqlite3VdbeJumpHere(v, 0); Thus, we have to again set its value to 1, in case of omitting jump. > >> } >> /* Get the VDBE program ready for execution > > 4. Can we test the new VDBE plan using EXPLAIN? I am wondering why all > plan changes are not tested using EXPLAIN. Well, it it is quite complicated to test EXPLAIN command since any change to query planner or code generator at all would result in rewriting such tests. Hence, once we decided to avoid using tests with EXPLAIN until we get stable code generation. ======================================================================= Subject: [PATCH] sql: remove redundant goto from VDBE prologue Structure of VDBE prologue: 0: OP_Init 0 N (address to start) 0 --| |-> 1: ... | | ... | | N: OP_Transaction <------------ | N+1: (Constant expressions to be saved in registers) | ... |-- M: OP_Goto 0 1 0 However, last opcode in VDBE program (i.e. OP_Goto) is generated always, despite the existence of OP_Transaction or constant expressions. Thus, VDBE program for queries like <SELECT * FROM table;> features redundant jump. Such useless jump wastes exectuion time (although it is executed once) and may affect jump prediction. This patch adds conditional branch for generating jump opcode finishing VDBE program: it is appended only if we need to start transaction or code constrant expressions. Closes #3231 --- src/box/sql/build.c | 105 +++++++++++++++++++++++------------------------- src/box/sql/parse.y | 2 +- src/box/sql/sqliteInt.h | 17 +++++++- 3 files changed, 68 insertions(+), 56 deletions(-) diff --git a/src/box/sql/build.c b/src/box/sql/build.c index 62d687b17..1c972c977 100644 --- a/src/box/sql/build.c +++ b/src/box/sql/build.c @@ -54,76 +54,73 @@ #include "box/tuple_format.h" #include "box/coll_id_cache.h" -/* - * This routine is called after a single SQL statement has been - * parsed and a VDBE program to execute that statement has been - * prepared. This routine puts the finishing touches on the - * VDBE program and resets the pParse structure for the next - * parse. - * - * Note that if an error occurred, it might be the case that - * no VDBE code was generated. - */ void -sqlite3FinishCoding(Parse * pParse) +sql_finish_coding(struct Parse *parse_context) { - sqlite3 *db; - Vdbe *v; - - assert(pParse->pToplevel == 0); - db = pParse->db; - if (pParse->nested) + if (parse_context->nested) return; - if (db->mallocFailed || pParse->nErr) { - if (pParse->rc == SQLITE_OK) - pParse->rc = SQLITE_ERROR; + assert(parse_context->pToplevel == NULL); + struct sqlite3 *db = parse_context->db; + if (db->mallocFailed || parse_context->nErr != 0) { + if (parse_context->rc == SQLITE_OK) + parse_context->rc = SQLITE_ERROR; return; } - - /* Begin by generating some termination code at the end of the - * vdbe program + /* + * Begin by generating some termination code at the end + * of the vdbe program */ - v = sqlite3GetVdbe(pParse); - assert(!pParse->isMultiWrite - || sqlite3VdbeAssertMayAbort(v, pParse->mayAbort)); - if (v) { + struct Vdbe *v = sqlite3GetVdbe(parse_context); + assert(!parse_context->isMultiWrite || + sqlite3VdbeAssertMayAbort(v, parse_context->mayAbort)); + if (v != NULL) { sqlite3VdbeAddOp0(v, OP_Halt); - if (db->mallocFailed == 0 || pParse->pConstExpr) { - int i; + if (db->mallocFailed == 0 || + parse_context->pConstExpr != NULL) { assert(sqlite3VdbeGetOp(v, 0)->opcode == OP_Init); sqlite3VdbeJumpHere(v, 0); - if (pParse->initiateTTrans) + if (parse_context->initiateTTrans) sqlite3VdbeAddOp0(v, OP_TTransaction); - if (db->init.busy == 0) - sqlite3VdbeChangeP5(v, 1); - - /* Code constant expressions that where factored out of inner loops */ - if (pParse->pConstExpr) { - ExprList *pEL = pParse->pConstExpr; - pParse->okConstFactor = 0; - for (i = 0; i < pEL->nExpr; i++) { - sqlite3ExprCode(pParse, pEL->a[i].pExpr, - pEL->a[i].u. + /* + * Code constant expressions that where + * factored out of inner loops. + */ + if (parse_context->pConstExpr != NULL) { + struct ExprList *exprs = + parse_context->pConstExpr; + parse_context->okConstFactor = 0; + for (int i = 0; i < exprs->nExpr; ++i) { + sqlite3ExprCode(parse_context, + exprs->a[i].pExpr, + exprs->a[i].u. iConstExprReg); } } - - /* Finally, jump back to the beginning of the executable code. */ - sqlite3VdbeGoto(v, 1); } - } - - /* Get the VDBE program ready for execution - */ - if (v && pParse->nErr == 0 && !db->mallocFailed) { - assert(pParse->iCacheLevel == 0); /* Disables and re-enables match */ - /* A minimum of one cursor is required if autoincrement is used - * See ticket [a696379c1f08866] + /* + * Finally, jump back to the beginning of + * the executable code. In fact, it is required + * only if some additional opcodes are generated. + * Otherwise, it would be useless jump: + * + * 0: OP_Init 0 vdbe_end ... + * 1: ... + * ... + * vdbe_end: OP_Goto 0 1 ... */ - sqlite3VdbeMakeReady(v, pParse); - pParse->rc = SQLITE_DONE; + if (parse_context->pConstExpr != NULL || + parse_context->initiateTTrans) + sqlite3VdbeGoto(v, 1); + else + sqlite3VdbeChangeP2(v, 0, 1); + } + /* Get the VDBE program ready for execution. */ + if (v != NULL && parse_context->nErr == 0 && !db->mallocFailed) { + assert(parse_context->iCacheLevel == 0); + sqlite3VdbeMakeReady(v, parse_context); + parse_context->rc = SQLITE_DONE; } else { - pParse->rc = SQLITE_ERROR; + parse_context->rc = SQLITE_ERROR; } } diff --git a/src/box/sql/parse.y b/src/box/sql/parse.y index 2e5f349c8..58f54e05f 100644 --- a/src/box/sql/parse.y +++ b/src/box/sql/parse.y @@ -110,7 +110,7 @@ static void disableLookaside(Parse *pParse){ input ::= ecmd. ecmd ::= explain cmdx SEMI. { if (!pParse->parse_only) - sqlite3FinishCoding(pParse); + sql_finish_coding(pParse); } ecmd ::= SEMI. { sqlite3ErrorMsg(pParse, "syntax error: empty request"); diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h index 01351a183..4d2bcafbc 100644 --- a/src/box/sql/sqliteInt.h +++ b/src/box/sql/sqliteInt.h @@ -3442,7 +3442,22 @@ void sqlite3NormalizeName(char *z); void sqlite3TokenInit(Token *, char *); int sqlite3KeywordCode(const unsigned char *, int); int sqlite3RunParser(Parse *, const char *, char **); -void sqlite3FinishCoding(Parse *); + +/** + * This routine is called after a single SQL statement has been + * parsed and a VDBE program to execute that statement has been + * prepared. This routine puts the finishing touches on the + * VDBE program and resets the pParse structure for the next + * parse. + * + * Note that if an error occurred, it might be the case that + * no VDBE code was generated. + * + * @param parse_context Current parsing context. + */ +void +sql_finish_coding(struct Parse *parse_context); + int sqlite3GetTempReg(Parse *); void sqlite3ReleaseTempReg(Parse *, int); int sqlite3GetTempRange(Parse *, int); -- 2.15.1
next prev parent reply other threads:[~2018-06-18 10:46 UTC|newest] Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top 2018-06-12 18:26 [tarantool-patches] " Nikita Pettik 2018-06-17 20:08 ` [tarantool-patches] " Vladislav Shpilevoy 2018-06-18 10:46 ` n.pettik [this message] 2018-06-18 11:06 ` Vladislav Shpilevoy 2018-06-18 17:45 ` n.pettik 2018-06-18 18:57 ` Vladislav Shpilevoy 2018-06-18 20:55 ` n.pettik 2018-06-18 21:03 ` Vladislav Shpilevoy 2018-06-19 8:21 ` Kirill Yukhin
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=28322F56-E52D-42C7-AE52-188D6F50AF63@tarantool.org \ --to=korablev@tarantool.org \ --cc=tarantool-patches@freelists.org \ --cc=v.shpilevoy@tarantool.org \ --subject='[tarantool-patches] Re: [PATCH] sql: remove redundant goto from VDBE prologue' \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox