prisma-engines icon indicating copy to clipboard operation
prisma-engines copied to clipboard

WIP(schema-wasm): support schema split into multiple files

Open SevInf opened this issue 1 year ago • 3 comments

Closes prisma/team-orm#1038

SevInf avatar Mar 22 '24 15:03 SevInf

WASM Query Engine file Size

Engine This PR Base branch Diff
Postgres 2.124MiB 2.124MiB 228.000B
Postgres (gzip) 836.395KiB 836.163KiB 238.000B
Mysql 2.092MiB 2.092MiB 228.000B
Mysql (gzip) 823.310KiB 823.329KiB -19.000B
Sqlite 1.988MiB 1.987MiB 306.000B
Sqlite (gzip) 784.003KiB 784.104KiB -103.000B

github-actions[bot] avatar Mar 26 '24 15:03 github-actions[bot]

CodSpeed Performance Report

Merging #4787 will improve performances by 5.67%

Comparing feat/multi-schema-fmt (e32d0dd) with main (dcdb692)

Summary

⚡ 1 improvements ✅ 10 untouched benchmarks

Benchmarks breakdown

Benchmark main feat/multi-schema-fmt Change
âš¡ large_read 8.1 ms 7.7 ms +5.67%

codspeed-hq[bot] avatar Mar 26 '24 15:03 codspeed-hq[bot]

✅ WASM query-engine performance won't change substantially (0.996x)

Full benchmark report
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/bench?schema=imdb_bench&sslmode=disable" \
node --experimental-wasm-modules query-engine/driver-adapters/executor/dist/bench.mjs
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
cpu: AMD EPYC 7763 64-Core Processor
runtime: node v18.20.0 (x64-linux)

benchmark                   time (avg)             (min … max)       p75       p99      p999
-------------------------------------------------------------- -----------------------------
• movies.findMany() (all - ~50K)
-------------------------------------------------------------- -----------------------------
Web Assembly: Baseline     288 ms/iter       (286 ms … 293 ms)    290 ms    293 ms    293 ms
Web Assembly: Latest       374 ms/iter       (371 ms … 378 ms)    376 ms    378 ms    378 ms
Web Assembly: Current      373 ms/iter       (373 ms … 376 ms)    374 ms    376 ms    376 ms
Node API: Current          195 ms/iter       (193 ms … 198 ms)    196 ms    198 ms    198 ms

summary for movies.findMany() (all - ~50K)
  Web Assembly: Current
   1.92x slower than Node API: Current
   1.3x slower than Web Assembly: Baseline
   1x faster than Web Assembly: Latest

• movies.findMany({ take: 2000 })
-------------------------------------------------------------- -----------------------------
Web Assembly: Baseline  11'664 µs/iter (11'508 µs … 12'446 µs) 11'673 µs 12'446 µs 12'446 µs
Web Assembly: Latest    15'564 µs/iter (14'964 µs … 21'262 µs) 15'262 µs 21'262 µs 21'262 µs
Web Assembly: Current   15'108 µs/iter (14'918 µs … 16'021 µs) 15'101 µs 16'021 µs 16'021 µs
Node API: Current        7'897 µs/iter   (7'742 µs … 8'220 µs)  7'934 µs  8'220 µs  8'220 µs

summary for movies.findMany({ take: 2000 })
  Web Assembly: Current
   1.91x slower than Node API: Current
   1.3x slower than Web Assembly: Baseline
   1.03x faster than Web Assembly: Latest

• movies.findMany({ where: {...}, take: 2000 })
-------------------------------------------------------------- -----------------------------
Web Assembly: Baseline   1'884 µs/iter   (1'738 µs … 3'619 µs)  1'848 µs  3'396 µs  3'619 µs
Web Assembly: Latest     2'422 µs/iter   (2'311 µs … 3'734 µs)  2'409 µs  3'033 µs  3'734 µs
Web Assembly: Current    2'368 µs/iter   (2'300 µs … 3'027 µs)  2'371 µs  2'741 µs  3'027 µs
Node API: Current        1'390 µs/iter   (1'302 µs … 1'630 µs)  1'398 µs  1'593 µs  1'630 µs

summary for movies.findMany({ where: {...}, take: 2000 })
  Web Assembly: Current
   1.7x slower than Node API: Current
   1.26x slower than Web Assembly: Baseline
   1.02x faster than Web Assembly: Latest

• movies.findMany({ include: { cast: true } take: 2000 }) (m2m)
-------------------------------------------------------------- -----------------------------
Web Assembly: Baseline     549 ms/iter       (540 ms … 570 ms)    560 ms    570 ms    570 ms
Web Assembly: Latest       757 ms/iter       (750 ms … 779 ms)    763 ms    779 ms    779 ms
Web Assembly: Current      757 ms/iter       (752 ms … 766 ms)    760 ms    766 ms    766 ms
Node API: Current          481 ms/iter       (469 ms … 494 ms)    488 ms    494 ms    494 ms

summary for movies.findMany({ include: { cast: true } take: 2000 }) (m2m)
  Web Assembly: Current
   1.57x slower than Node API: Current
   1.38x slower than Web Assembly: Baseline
   1x faster than Web Assembly: Latest

• movies.findMany({ where: {...}, include: { cast: true } take: 2000 }) (m2m)
-------------------------------------------------------------- -----------------------------
Web Assembly: Baseline  76'114 µs/iter (75'805 µs … 76'876 µs) 76'427 µs 76'876 µs 76'876 µs
Web Assembly: Latest       108 ms/iter       (107 ms … 110 ms)    109 ms    110 ms    110 ms
Web Assembly: Current      108 ms/iter       (107 ms … 110 ms)    108 ms    110 ms    110 ms
Node API: Current       64'024 µs/iter (62'923 µs … 65'224 µs) 65'215 µs 65'224 µs 65'224 µs

summary for movies.findMany({ where: {...}, include: { cast: true } take: 2000 }) (m2m)
  Web Assembly: Current
   1.68x slower than Node API: Current
   1.41x slower than Web Assembly: Baseline
   1x faster than Web Assembly: Latest

• movies.findMany({ take: 2000, include: { cast: { include: { person: true } } } })
-------------------------------------------------------------- -----------------------------
Web Assembly: Baseline     974 ms/iter       (971 ms … 980 ms)    979 ms    980 ms    980 ms
Web Assembly: Latest     1'262 ms/iter   (1'254 ms … 1'277 ms)  1'267 ms  1'277 ms  1'277 ms
Web Assembly: Current    1'265 ms/iter   (1'259 ms … 1'286 ms)  1'271 ms  1'286 ms  1'286 ms
Node API: Current          894 ms/iter       (868 ms … 934 ms)    920 ms    934 ms    934 ms

summary for movies.findMany({ take: 2000, include: { cast: { include: { person: true } } } })
  Web Assembly: Current
   1.42x slower than Node API: Current
   1.3x slower than Web Assembly: Baseline
   1x faster than Web Assembly: Latest

• movie.findMany({ where: { ... }, take: 2000, include: { cast: { include: { person: true } } } })
-------------------------------------------------------------- -----------------------------
Web Assembly: Baseline     138 ms/iter       (136 ms … 147 ms)    138 ms    147 ms    147 ms
Web Assembly: Latest       175 ms/iter       (174 ms … 176 ms)    175 ms    176 ms    176 ms
Web Assembly: Current      174 ms/iter       (174 ms … 175 ms)    175 ms    175 ms    175 ms
Node API: Current          106 ms/iter       (105 ms … 107 ms)    107 ms    107 ms    107 ms

summary for movie.findMany({ where: { ... }, take: 2000, include: { cast: { include: { person: true } } } })
  Web Assembly: Current
   1.65x slower than Node API: Current
   1.27x slower than Web Assembly: Baseline
   1x faster than Web Assembly: Latest

• movie.findMany({ where: { reviews: { author: { ... } }, take: 100 }) (to-many -> to-one)
-------------------------------------------------------------- -----------------------------
Web Assembly: Baseline     869 µs/iter     (811 µs … 1'501 µs)    866 µs  1'358 µs  1'501 µs
Web Assembly: Latest     1'215 µs/iter   (1'147 µs … 1'881 µs)  1'214 µs  1'697 µs  1'881 µs
Web Assembly: Current    1'212 µs/iter   (1'155 µs … 1'650 µs)  1'215 µs  1'531 µs  1'650 µs
Node API: Current          774 µs/iter     (694 µs … 1'443 µs)    789 µs  1'096 µs  1'443 µs

summary for movie.findMany({ where: { reviews: { author: { ... } }, take: 100 }) (to-many -> to-one)
  Web Assembly: Current
   1.57x slower than Node API: Current
   1.39x slower than Web Assembly: Baseline
   1x faster than Web Assembly: Latest

• movie.findMany({ where: { cast: { person: { ... } }, take: 100 }) (m2m -> to-one)
-------------------------------------------------------------- -----------------------------
Web Assembly: Baseline     860 µs/iter     (813 µs … 1'392 µs)    860 µs  1'305 µs  1'392 µs
Web Assembly: Latest     1'188 µs/iter   (1'131 µs … 1'652 µs)  1'195 µs  1'497 µs  1'652 µs
Web Assembly: Current    1'208 µs/iter   (1'140 µs … 1'873 µs)  1'205 µs  1'755 µs  1'873 µs
Node API: Current          775 µs/iter     (710 µs … 1'064 µs)    797 µs    933 µs  1'064 µs

summary for movie.findMany({ where: { cast: { person: { ... } }, take: 100 }) (m2m -> to-one)
  Web Assembly: Current
   1.56x slower than Node API: Current
   1.41x slower than Web Assembly: Baseline
   1.02x slower than Web Assembly: Latest

After changes in e32d0dd22528849a0f4d9c892df73d6a3a0e22fe

github-actions[bot] avatar Mar 26 '24 15:03 github-actions[bot]

Using prisma-fmt-wasm, the following now works:

  • ./prisma/schema.prisma is a self-standing Prisma schema that is valid on its own

    datasource db {
      provider = "postgresql"
      url = env("DBURL")
    }
    
    model A {
      id String @id
      b_id String @unique
      b B @relation(fields: [b_id], references: [id])
    }
    
    model B {
      id String @id
      a  A?
    }
    
  • schema-1.prisma is only pair when paired with some other Prisma

    model B {
      id String @id
      a  A?
    }
    
  • schema-2.prisma is only pair when paired with some other Prisma

    datasource db {
      provider = "postgresql"
      url = env("DBURL")
    }
    
    model A {
      id String @id
      b_id String @unique
      b B @relation(fields: [b_id], references: [id])
    }
    
  • index.cjs shows how the validate function works:

    const fs = require('node:fs/promises')
    const path = require('node:path')
    const { validate } = require('./prisma_schema_build')
    
    async function main() {
      const schema = await fs.readFile(path.join(__dirname, 'prisma/schema.prisma'), 'utf-8')
      const schema1 = await fs.readFile(path.join(__dirname, 'prisma/schema-1.prisma'), 'utf-8')
      const schema2 = await fs.readFile(path.join(__dirname, 'prisma/schema-2.prisma'), 'utf-8')
    
      validate(JSON.stringify({ prismaSchema: schema }))
      console.log('[validate] schema.prisma is valid')
    
      try {
        validate(JSON.stringify({ prismaSchema: schema1 }))
      } catch (e) {
        console.log('[validate] schema1.prisma is not valid on its own')
        console.error(JSON.parse(e.message).message)
      }
    
      try {
        validate(JSON.stringify({ prismaSchema: schema2 }))
      } catch (e) {
        console.log('[validate] schema2.prisma is not valid on its own')
        console.error(JSON.parse(e.message).message)
      }
    
      validate(JSON.stringify({ prismaSchema: [['schema-1.prisma', schema1], ['schema-2.prisma', schema2]] }))
      console.log('[validate] schema1.prisma + schema.2.prisma are valid')
    }
    
    main()
    
  • Output: Screenshot 2024-04-05 at 12 52 55

jkomyno avatar Apr 05 '24 09:04 jkomyno