From 97f312a1b536c92440b04ec3dd743fc2802ab150 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 13 Aug 2021 15:48:25 +0200 Subject: Optimize query_dependents() using prepared queries --- bpkg/database.hxx | 1 + bpkg/odb.sh | 5 +++-- bpkg/package.cxx | 45 ++++++++++++++++++++++++++++++++++++++++++--- bpkg/package.hxx | 6 ++++++ bpkg/pkg-build.cxx | 6 +++--- bpkg/pkg-drop.cxx | 2 +- 6 files changed, 56 insertions(+), 9 deletions(-) diff --git a/bpkg/database.hxx b/bpkg/database.hxx index 1961272..c7f059d 100644 --- a/bpkg/database.hxx +++ b/bpkg/database.hxx @@ -21,6 +21,7 @@ namespace bpkg { using odb::query; + using odb::prepared_query; using odb::result; using odb::session; diff --git a/bpkg/odb.sh b/bpkg/odb.sh index 7f494e1..75c6d2d 100755 --- a/bpkg/odb.sh +++ b/bpkg/odb.sh @@ -50,6 +50,7 @@ $odb "${inc[@]}" \ --hxx-prologue '#include ' \ --hxx-prologue '#include ' \ --hxx-prologue '#include ' \ - --include-with-brackets --include-prefix bpkg --guard-prefix BPKG \ - --schema main --schema-version-table main.schema_version \ + --generate-prepared --include-with-brackets --include-prefix bpkg \ + --guard-prefix BPKG --schema main \ + --schema-version-table main.schema_version \ --sqlite-override-null package.hxx diff --git a/bpkg/package.cxx b/bpkg/package.cxx index 7995c34..8ad178d 100644 --- a/bpkg/package.cxx +++ b/bpkg/package.cxx @@ -684,10 +684,49 @@ namespace bpkg const package_name& dep, database& dep_db) { + // Prepare and cache this query since it's executed a lot. Note that we + // have to cache one per database. + // using query = query; + using prep_query = prepared_query; + + struct params + { + string name; + string config; // Configuration UUID. + string query_name; + }; + + params* qp; + string qn (db.uuid.string () + "-package-dependent-query"); + prep_query pq (db.lookup_query (qn.c_str (), qp)); + + if (!pq) + { + unique_ptr p (qp = new params ()); + p->query_name = move (qn); + + query q ("prerequisite = " + query::_ref (p->name) + "AND" + + "configuration = " + query::_ref (p->config)); - return db.query ( - "prerequisite = " + query::_val (dep.string ()) + "AND" + - "configuration = " + query::_val (dep_db.uuid.string ())); + pq = db.prepare_query (p->query_name.c_str (), q); + db.cache_query (pq, move (p)); + } + + qp->name = dep.string (); + qp->config = dep_db.uuid.string (); + + return pq.execute (); + } + + vector + query_dependents_cache (database& db, + const package_name& dep, + database& dep_db) + { + vector r; + for (package_dependent& pd: query_dependents (db, dep, dep_db)) + r.push_back (move (pd)); + return r; } } diff --git a/bpkg/package.hxx b/bpkg/package.hxx index a0e809a..1a62cd9 100644 --- a/bpkg/package.hxx +++ b/bpkg/package.hxx @@ -1314,6 +1314,12 @@ namespace bpkg const package_name& dependency, database& dependency_db); + // As above but cache the result in a vector. This version should be used if + // query_dependents*() may be called recursively. + // + vector + query_dependents_cache (database&, const package_name&, database&); + // Database and package name pair. // // It is normally used as a key for maps containing data for packages across diff --git a/bpkg/pkg-build.cxx b/bpkg/pkg-build.cxx index d8e5cda..1e8e9dd 100644 --- a/bpkg/pkg-build.cxx +++ b/bpkg/pkg-build.cxx @@ -1839,7 +1839,7 @@ namespace bpkg for (database& ddb: pdb.dependent_configs ()) { - for (auto& pd: query_dependents (ddb, n, pdb)) + for (auto& pd: query_dependents_cache (ddb, n, pdb)) { package_name& dn (pd.name); auto i (map_.find (ddb, dn)); @@ -2938,7 +2938,7 @@ namespace bpkg for (database& ddb: db.dependent_configs ()) { - for (auto& pd: query_dependents (ddb, nm, db)) + for (auto& pd: query_dependents_cache (ddb, nm, db)) { // Note that we cannot end up with an infinite recursion for // configured packages due to a dependency cycle (see order() for @@ -2998,7 +2998,7 @@ namespace bpkg for (database& ddb: db.dependent_configs ()) { - for (auto& pd: query_dependents (ddb, sp->name, db)) + for (auto& pd: query_dependents_cache (ddb, sp->name, db)) { shared_ptr dsp ( ddb.load (pd.name)); diff --git a/bpkg/pkg-drop.cxx b/bpkg/pkg-drop.cxx index e060e96..dfae66f 100644 --- a/bpkg/pkg-drop.cxx +++ b/bpkg/pkg-drop.cxx @@ -110,7 +110,7 @@ namespace bpkg { for (database& ddb: db.dependent_configs ()) { - for (auto& pd: query_dependents (ddb, p->name, db)) + for (auto& pd: query_dependents_cache (ddb, p->name, db)) { const package_name& dn (pd.name); -- cgit v1.1