From b6f3f6dd332b93d0e1a5aaba169832a36c87c25f Mon Sep 17 00:00:00 2001 From: Fedor Indutny <238531+indutny@users.noreply.github.com> Date: Sat, 12 Oct 2024 21:56:23 -0700 Subject: [PATCH] sqlite: cache column names in stmt.all() While the statement is running, it is impossible to modify the column names and thus it is beneficial to create the host-language (JS) keys once per all rows and reuse them for all results. With this change the performance of `.all()` improves by around 25% depending on the number of columns and rows in the result. --- src/node_sqlite.cc | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/node_sqlite.cc b/src/node_sqlite.cc index df6bb45ad60e7d..f7025373f2c6a3 100644 --- a/src/node_sqlite.cc +++ b/src/node_sqlite.cc @@ -561,23 +561,32 @@ void StatementSync::All(const FunctionCallbackInfo& args) { auto reset = OnScopeLeave([&]() { sqlite3_reset(stmt->statement_); }); int num_cols = sqlite3_column_count(stmt->statement_); LocalVector rows(isolate); + LocalVector row_keys(isolate); while ((r = sqlite3_step(stmt->statement_)) == SQLITE_ROW) { - LocalVector row_keys(isolate); - row_keys.reserve(num_cols); + if (row_keys.size() == 0) { + row_keys.reserve(num_cols); + + for (int i = 0; i < num_cols; ++i) { + Local key; + if (!stmt->ColumnNameToName(i).ToLocal(&key)) return; + row_keys.emplace_back(key); + } + } + LocalVector row_values(isolate); row_values.reserve(num_cols); - for (int i = 0; i < num_cols; ++i) { - Local key; - if (!stmt->ColumnNameToName(i).ToLocal(&key)) return; + for (size_t i = 0; i < row_keys.size(); ++i) { Local val; if (!stmt->ColumnToValue(i).ToLocal(&val)) return; - row_keys.emplace_back(key); row_values.emplace_back(val); } - Local row = Object::New( - isolate, Null(isolate), row_keys.data(), row_values.data(), num_cols); + Local row = Object::New(isolate, + Null(isolate), + row_keys.data(), + row_values.data(), + row_keys.size()); rows.emplace_back(row); }