diff --git a/query-engine/driver-adapters/executor/bench/queries.json b/query-engine/driver-adapters/executor/bench/queries.json index e143da135acc..5410f162be11 100644 --- a/query-engine/driver-adapters/executor/bench/queries.json +++ b/query-engine/driver-adapters/executor/bench/queries.json @@ -1,6 +1,6 @@ [ { - "description": "movies.findMany() (all - 25000)", + "description": "movies.findMany() (all - ~50K)", "query": { "action": "findMany", "modelName": "Movie", @@ -59,7 +59,12 @@ "cast": true }, "selection": { - "$scalars": true + "$scalars": true, + "cast": { + "selection": { + "$scalars": true + } + } } } } @@ -82,7 +87,12 @@ "cast": true }, "selection": { - "$scalars": true + "$scalars": true, + "cast": { + "selection": { + "$scalars": true + } + } } } } @@ -104,7 +114,16 @@ } }, "selection": { - "$scalars": true + "$scalars": true, + "cast": { + "selection": { + "person": { + "selection": { + "$scalars": true + } + } + } + } } } } @@ -131,7 +150,16 @@ } }, "selection": { - "$scalars": true + "$scalars": true, + "cast": { + "selection": { + "person": { + "selection": { + "$scalars": true + } + } + } + } } } } diff --git a/query-engine/driver-adapters/executor/bench/schema.prisma b/query-engine/driver-adapters/executor/bench/schema.prisma index a45c1e62b4cc..6346afed158d 100644 --- a/query-engine/driver-adapters/executor/bench/schema.prisma +++ b/query-engine/driver-adapters/executor/bench/schema.prisma @@ -5,7 +5,7 @@ datasource db { generator foo { provider = "prisma-client-js" - previewFeatures = ["driverAdapters"] + previewFeatures = ["driverAdapters", "relationJoins"] } model Movie { diff --git a/query-engine/driver-adapters/executor/src/bench.ts b/query-engine/driver-adapters/executor/src/bench.ts index e01c333e5c68..afccf8b2f7fc 100644 --- a/query-engine/driver-adapters/executor/src/bench.ts +++ b/query-engine/driver-adapters/executor/src/bench.ts @@ -41,11 +41,18 @@ async function main(): Promise { const withErrorCapturing = bindAdapter(pg); // We build two decorators for recording and replaying db queries. - const { recorder, replayer } = recording(withErrorCapturing); + const { recorder, replayer, recordings } = recording(withErrorCapturing); // We exercise the queries recording them await recordQueries(recorder, datamodel, prismaQueries); + // Dump recordings if requested + if (process.env.BENCH_RECORDINGS_FILE != null) { + const recordingsJson = JSON.stringify(recordings.data(), null, 2); + await fs.writeFile(process.env.BENCH_RECORDINGS_FILE, recordingsJson); + debug(`Recordings written to ${process.env.BENCH_RECORDINGS_FILE}`); + } + // Then we benchmark the execution of the queries but instead of hitting the DB // we fetch results from the recordings, thus isolating the performance // of the engine + driver adapter code from that of the DB IO. @@ -57,23 +64,37 @@ async function recordQueries( datamodel: string, prismaQueries: any ): Promise { - const qe = await initQeWasmBaseLine(adapter, datamodel); - await qe.connect(""); + // Different engines might have made different SQL queries to complete the same Prisma Query, + // so we record the results of all engines for the benchmarking phase. + const napi = await initQeNapiCurrent(adapter, datamodel); + await napi.connect(""); + const wasmCurrent = await initQeWasmCurrent(adapter, datamodel); + await wasmCurrent.connect(""); + const wasmBaseline = await initQeWasmBaseLine(adapter, datamodel); + await wasmBaseline.connect(""); + const wasmLatest = await initQeWasmLatest(adapter, datamodel); + await wasmLatest.connect(""); try { - for (const prismaQuery of prismaQueries) { - const { description, query } = prismaQuery; - const res = await qe.query(JSON.stringify(query), "", undefined); - - const errors = JSON.parse(res).errors; - if (errors != null && errors.length > 0) { - throw new Error( - `Query failed for ${description}: ${JSON.stringify(res)}` - ); + for (const qe of [napi, wasmCurrent, wasmBaseline, wasmLatest]) { + for (const prismaQuery of prismaQueries) { + const { description, query } = prismaQuery; + const res = await qe.query(JSON.stringify(query), "", undefined); + console.log(res[9]); + + const errors = JSON.parse(res).errors; + if (errors != null) { + throw new Error( + `Query failed for ${description}: ${JSON.stringify(res)}` + ); + } } } } finally { - await qe.disconnect(""); + await napi.disconnect(""); + await wasmCurrent.disconnect(""); + await wasmBaseline.disconnect(""); + await wasmLatest.disconnect(""); } } diff --git a/query-engine/driver-adapters/executor/src/recording.ts b/query-engine/driver-adapters/executor/src/recording.ts index 1ac2e8aef2e5..0602cb69dc4e 100644 --- a/query-engine/driver-adapters/executor/src/recording.ts +++ b/query-engine/driver-adapters/executor/src/recording.ts @@ -13,6 +13,7 @@ export function recording(adapter: DriverAdapter) { return { recorder: recorder(adapter, recordings), replayer: replayer(adapter, recordings), + recordings: recordings, }; } @@ -31,9 +32,7 @@ function recorder(adapter: DriverAdapter, recordings: Recordings) { return result; }, executeRaw: async (params) => { - const result = await adapter.executeRaw(params); - recordings.addCommandResults(params, result); - return result; + throw new Error("Not implemented"); }, }; } @@ -70,6 +69,16 @@ function createInMemoryRecordings() { }; return { + data: (): Map => { + const map = new Map(); + for (const [key, value] of queryResults.entries()) { + value.map((resultSet) => { + map[key] = resultSet; + }); + } + return map; + }, + addQueryResults: (params: Query, result: Result) => { const key = queryToKey(params); queryResults.set(key, result);