Skip to content

Discussion: Deno Port #2225

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
grantcarthew opened this issue May 22, 2020 · 16 comments
Open

Discussion: Deno Port #2225

grantcarthew opened this issue May 22, 2020 · 16 comments

Comments

@grantcarthew
Copy link

grantcarthew commented May 22, 2020

I have been having a close look at deno and have had an attempt to build a solution with it. It is delightfully refreshing to not have to build a project, and to be able to use the current JavaScript language features.

At this point in time, there are limited options for working with PostgreSQL.

The main project on the Third Party Modules list, deno-postgres, has one major feature missing and one show stopper bug. I considered trying to contribute to the project however after having a look at what has been done with this project, there are huge amounts of work required.

I looked for an issue being raised here about porting over to Deno and there was none so I'm bringing up the discussion.

I am no expert on Deno although I did migrate a couple of projects over to it already being pg-format and cuid.

As far as I am aware, to migrate this project so that it will work on Deno would require the following:

I imagine the mix of js and ts modules would be an issue. I'm not a TypeScript guy. There are probably a few other issues which will arise as you would expect.

The deno-postgres project has been created by one of the main Deno developers, Bartek Iwańczuk, and he has stated that he is busy with the core of Deno at the moment. He is going to work on it soon. It is not a fork of this project though and is missing many features at this time.

When you consider the vast amount of work that has been put into this project, it seems a shame to re-invent the wheel. Both Node.js and Deno run JavaScript. That being said, Deno tries as much as possible to stick to the Web Standard APIs. This will mean significant changes and therefore it is unlikely to be able to keep the Node.js and Deno port in sync.

I'm just opening the discussion here to gauge interest.

@qimingweng
Copy link

It would be very ideal if this could happen, and happy to contribute if the node-postgres maintainers can indicate their position/opinions.

@malthe
Copy link

malthe commented May 22, 2020

Fwiw, I wrote a rather fully-featured client for Node.js in TypeScript: https://github.com/malthe/ts-postgres. I do have plans to port it to Deno, but I was rather hoping for a single-source approach.

@brianc
Copy link
Owner

brianc commented May 22, 2020

I'm totally cool with any kind of port or fork you think is good to get postgres support more built out on Deno. This part of the library in particular should be useful as its written in TypeScript already and doesn't have many 3rd party dependencies. If there's a way to remove all the node dependencies and make it portable to Deno while maintaining the same performance characteristics I'd be open to discussing merging that here & have re-use across platforms.

That being said, my primary focus for the rest of 2020 is to continue to improve perf on this library, modernize it (some of the code is >10 years old!) and provide an extremely robust and well tested platform for node.js postgres connections. I'm happy to help out in a limited capacity with Deno support, but I think its best for the community if I continue to focus on primarily supporting node.js. I've been involved in the node community for >10 years now, and I watched trends come and go. If Deno becomes huge and replaces node, that'll be interesting, but even then I will still focus on support this library and the millions of installations it has throughout the world. That's my primary focus, and I don't have any plans to refocus in the foreseeable future. If I check the weekly installs and it drops below a few thousand I'll probably retire from open source at that point...but as far as I can see that's years from now. 😄

Who knows! Anything could happen & I'm happy to help out anywhere I can so long as it doesn't detract from my focus on this lib! Also, this code is all open source so feel free to base any implementation on it. All I ask, for the community's sake, is that you take the time to PR any bug fixes you find in any ports back here....I've sunk literally thousands of hours into this project over the years (mostly GH issue triage, bug research, etc) and would be happy to merge any improvements that "life all boats" like rising tides are wont to do.

@malthe would you be interested in trying pg-protocol in your own library actually?...it's very, very battle tested protocol parser for postgres supporting every message type defined & totally written in TypeScript! Might be a good move to pool our efforts rather than write different protocol parsers. An example would be you find a perf improvement in parsing, you put it into pg-protocol and it impacts your lib and the millions of installs of node-postgres at the same time! 👯 Happy to make you a collaborator on this repo after a couple PRs w/ fixes.

I know ts-postgres does some different things wrt batching & stuff I'm going to work on here in the nearish future, but an entire from the ground rewrite of parsing in your module is probably redundant if you want to use pg-protocol. Either way...cool project!

Perhaps in the future we can consolidate our efforts and improve things for node & postgres as a whole in this project instead of fragmenting the module landscape...though I'm well aware that's the open source way and a the node community has always trended really hard that way. 🤷

@grantcarthew
Copy link
Author

That's a great reply. Thanks @brianc.

How about moving these projects under a GitHub Org? It's great to have a package under your username and being in control. I love working in my own little world. That being said, I believe this is one of the reasons that the js/open source is fragmented.

Having a Postgres based org would give confidence to the community that the project will not be abandoned by an author. I forked the pg-format module to convert to Deno and am offering to give it back to @rpedela here. It would make sense to put these types of modules under a common org.

@brianc, you are the perfect person to start such an organization.

@malthe
Copy link

malthe commented May 24, 2020

@brianc pg-protocol looks good; if I can get around to it, I'll try and see if it'll fit easily into the codebase – because you're absolutely right, it would be great to consolidate around a single implementation for the protocol. When I wrote the code I don't think there was such a package available, at least not written in TypeScript.

@alexgleason
Copy link

This library actually does work in Deno now, but the performance is so bad unfortunately.

deno-postgres now exists, which has acceptable performance on Deno, but lacks support for streaming/listen/notify and has some other problems I am still struggling with.

@brianc
Copy link
Owner

brianc commented Jun 18, 2024

but the performance is so bad unfortunately.

strange that performance is so bad...I wonder why? Maybe some kinda stream adapter? or their buffer adapter is slow? There aren't very many node dependencies in this library outside of buffer & stream...shouldn't be too hard to speed it up. I haven't done a benchmark recently on converting pg-protocol from using node's buffer object to arraybuffers & typed arrays...that'd probably be a good first step

@alexgleason
Copy link

@brianc I actually do have a high-level benchmark of my application code.

deno-postgres on Deno:

cpu: AMD Ryzen 7 PRO 5850U with Radeon Graphics
runtime: deno 1.44.2 (x86_64-unknown-linux-gnu)

file:///home/alex/Projects/nostrify/src/NDatabase.bench.ts
benchmark                                                      time (avg)        iter/s             (min … max)       p75       p99      p995
--------------------------------------------------------------------------------------------------------------- -----------------------------
NDatabase.event                                                  1.3 ms/iter         771.5     (1.02 ms … 2.04 ms) 1.45 ms 2.01 ms 2.04 ms
NDatabase.event with many tags                                  94.6 ms/iter          10.6   (91.61 ms … 98.37 ms) 96.6 ms 98.37 ms 98.37 ms
NDatabase.query by id                                         168.54 µs/iter       5,933.1 (138.43 µs … 682.99 µs) 186.41 µs 338.75 µs 399.52 µs
NDatabase.query by multiple ids                               168.39 µs/iter       5,938.5 (153.84 µs … 815.77 µs) 164.82 µs 280.63 µs 353.84 µs
NDatabase.query by kind                                         1.69 ms/iter         591.0     (1.47 ms … 2.81 ms) 1.78 ms 2.21 ms 2.39 ms
NDatabase.query by multiple kinds                             418.81 µs/iter       2,387.7  (369.98 µs … 891.2 µs) 423.51 µs 704 µs 751.41 µs
NDatabase.query by author                                     258.73 µs/iter       3,865.0  (226.8 µs … 781.89 µs) 253.79 µs 480.78 µs 532.2 µs
NDatabase.query by multiple authors                           264.72 µs/iter       3,777.5 (233.75 µs … 821.67 µs) 259.95 µs 497.12 µs 519.08 µs
NDatabase.query replaceable event by author                   163.04 µs/iter       6,133.6 (149.62 µs … 535.03 µs) 159.47 µs 283.57 µs 347.29 µs
NDatabase.query parameterized replaceable event by author     263.93 µs/iter       3,788.9  (236.51 µs … 999.4 µs) 258.47 µs 463.72 µs 499.74 µs
NDatabase.query by single tag                                 251.86 µs/iter       3,970.5  (234.6 µs … 517.11 µs) 249.37 µs 376.08 µs 446.38 µs
NDatabase.query by multiple tags                               429.4 µs/iter       2,328.8 (393.77 µs … 896.93 µs) 435.18 µs 616.76 µs 672.49 µs
NDatabase.query many events by tag                            438.78 µs/iter       2,279.0  (397.83 µs … 819.7 µs) 435.61 µs 700.37 µs 714.08 µs
NDatabase.query by kind and pubkey                            173.61 µs/iter       5,760.0 (159.37 µs … 601.38 µs) 171.11 µs 282.56 µs 363.81 µs
NDatabase.query by multiple kinds and pubkey                  192.48 µs/iter       5,195.3 (178.93 µs … 642.47 µs) 191.02 µs 280.42 µs 378.41 µs
NDatabase.query by kind and multiple pubkeys                  345.95 µs/iter       2,890.6      (309.72 µs … 4 ms) 341.62 µs 610.54 µs 633.46 µs
NDatabase.query by multiple kinds and multiple pubkeys        360.88 µs/iter       2,771.0 (329.51 µs … 731.52 µs) 357.26 µs 620.75 µs 642.78 µs

node-postgres on Deno:

cpu: AMD Ryzen 7 PRO 5850U with Radeon Graphics
runtime: deno 1.44.2 (x86_64-unknown-linux-gnu)

file:///home/alex/Projects/nostrify/src/NDatabase.bench.ts
benchmark                                                      time (avg)        iter/s             (min … max)       p75       p99      p995
--------------------------------------------------------------------------------------------------------------- -----------------------------
NDatabase.event                                               143.16 ms/iter           7.0 (129.92 ms … 154.67 ms) 150.91 ms 154.67 ms 154.67 ms
NDatabase.event with many tags                                145.61 ms/iter           6.9 (134.26 ms … 157.12 ms) 151.94 ms 157.12 ms 157.12 ms
NDatabase.query by id                                          44.18 ms/iter          22.6   (43.35 ms … 47.56 ms) 44.36 ms 47.56 ms 47.56 ms
NDatabase.query by multiple ids                                43.98 ms/iter          22.7    (43.4 ms … 44.51 ms) 44.2 ms 44.51 ms 44.51 ms
NDatabase.query by kind                                        44.15 ms/iter          22.6   (43.45 ms … 48.25 ms) 44.28 ms 48.25 ms 48.25 ms
NDatabase.query by multiple kinds                              44.17 ms/iter          22.6   (43.43 ms … 47.81 ms) 44.32 ms 47.81 ms 47.81 ms
NDatabase.query by author                                      44.35 ms/iter          22.5    (43.3 ms … 48.46 ms) 44.19 ms 48.46 ms 48.46 ms
NDatabase.query by multiple authors                            45.12 ms/iter          22.2   (43.15 ms … 48.13 ms) 47.65 ms 48.13 ms 48.13 ms
NDatabase.query replaceable event by author                    44.18 ms/iter          22.6   (43.44 ms … 47.29 ms) 44.11 ms 47.29 ms 47.29 ms
NDatabase.query parameterized replaceable event by author      44.95 ms/iter          22.2   (43.24 ms … 48.82 ms) 44.66 ms 48.82 ms 48.82 ms
NDatabase.query by single tag                                  44.92 ms/iter          22.3    (43.3 ms … 48.27 ms) 44.44 ms 48.27 ms 48.27 ms
NDatabase.query by multiple tags                               44.74 ms/iter          22.4    (43.48 ms … 48.1 ms) 44.54 ms 48.1 ms 48.1 ms
NDatabase.query many events by tag                             45.08 ms/iter          22.2   (42.96 ms … 48.49 ms) 47.89 ms 48.49 ms 48.49 ms
NDatabase.query by kind and pubkey                              45.1 ms/iter          22.2   (43.39 ms … 49.03 ms) 47.3 ms 49.03 ms 49.03 ms
NDatabase.query by multiple kinds and pubkey                   45.09 ms/iter          22.2   (43.48 ms … 48.32 ms) 47.46 ms 48.32 ms 48.32 ms
NDatabase.query by kind and multiple pubkeys                   44.56 ms/iter          22.4   (43.08 ms … 48.43 ms) 44.5 ms 48.43 ms 48.43 ms
NDatabase.query by multiple kinds and multiple pubkeys         44.01 ms/iter          22.7   (43.44 ms … 44.85 ms) 44.35 ms 44.85 ms 44.85 ms

There are some confounding variables. I am using Kysely for both benchmarks. The built-in Postgres adapter for node-postgres, and a custom adapter for deno-postgres.

However I'm not sure what causes a 100x decline in performance.

If you have any existing benchmarks you'd like me to try, I can adapt them to Deno and compare the libraries directly. Being able to use this library would help me immensely because I need streaming/listen/notify for my project, so I'm motivated to do it.

@alexgleason
Copy link

@brianc Is this the benchmark you recommend? https://github.com/brianc/node-postgres/blob/master/packages/pg/bench.js I will port it and test directly against deno-postgres in Deno.

@brianc
Copy link
Owner

brianc commented Jun 19, 2024

yeah it's a hideously bad benchmark but its what i use to check for major perf regressions 😬

@alexgleason
Copy link

@brianc Here's the benchmark on my laptop with Deno. Results are similar to the earlier benchmark - it still seems very slow. Do you glean anything from this?

start
warmup done

little queries: 103
qps 20.6
on my laptop best so far seen 733 qps

sequence queries: 5722
qps 1144.4
on my laptop best so far seen 1309 qps

insert queries: 113
qps 22.6
on my laptop best so far seen 6445 qps

Warming up bytea test
bytea warmup done
bytea time: 5718 ms
bytea length: 104857600 bytes
on my laptop best so far seen 1107ms and 104857600 bytes

little queries: 105
qps 21
on my laptop best so far seen 733 qps

sequence queries: 5854
qps 1170.8
on my laptop best so far seen 1309 qps

insert queries: 113
qps 22.6
on my laptop best so far seen 6445 qps

Warming up bytea test
bytea warmup done
bytea time: 10405 ms
bytea length: 104857600 bytes
on my laptop best so far seen 1107ms and 104857600 bytes

little queries: 105
qps 21
on my laptop best so far seen 733 qps

sequence queries: 5862
qps 1172.4
on my laptop best so far seen 1309 qps

insert queries: 114
qps 22.8
on my laptop best so far seen 6445 qps

Warming up bytea test
bytea warmup done
bytea time: 15125 ms
bytea length: 104857600 bytes
on my laptop best so far seen 1107ms and 104857600 bytes

little queries: 105
qps 21
on my laptop best so far seen 733 qps

sequence queries: 5714
qps 1142.8
on my laptop best so far seen 1309 qps

insert queries: 113
qps 22.6
on my laptop best so far seen 6445 qps

Warming up bytea test
bytea warmup done
bytea time: 20061 ms
bytea length: 104857600 bytes
on my laptop best so far seen 1107ms and 104857600 bytes

The benchmark is here: https://gist.github.com/alexgleason/64ed1a1e44e40284b3c379b4331eb340

You can reproduce it by running this:

deno run -A https://gist.githubusercontent.com/alexgleason/64ed1a1e44e40284b3c379b4331eb340/raw/21ef7351ff564e51a1790f5accb169cbed1ff7e2/node-postgres-deno-bench.ts

cc @bartlomieju, might find this interesting.

@alexgleason
Copy link

@brianc Any other thoughts on this benchmark? Thanks!

@zhang-wenchao
Copy link

Are there any updates?

@alexgleason
Copy link

alexgleason commented Aug 27, 2024

@zhang-wenchao I switched to postgresjs and it has the best performance on Deno of any library I tried, plus all the same features of this library. For best performance, you have to use the version from deno.land, not npm:

https://deno.land/x/postgresjs

@morpig
Copy link

morpig commented Oct 12, 2024

EDIT: right after reading the entire issue, seems to be something to do with node's compat API in deno.

coming to this thread since deno 2.0 release.

noticed that simple SELECT WHERE query are 4-5x slower than node/bun. anything I can do to be helpful?

Screenshot 2024-10-12 at 10 39 41
import pg from 'pg'
const { Client } = pg
const client = new Client({
    connectionString: 'postgresql://a:[email protected]:6432/public?sslmode=true'
})
await client.connect()
 
async function fetch() {
    const startPerf = performance.now();
    const res = await client.query('SELECT "id", "name", "email", "is_blocked" from "Users" where "Users"."id" = $1', ['1129c38d-874b-4d1b-9b88-08fee0f39f95'])
    console.log(`${new Date()}: ${Math.round(performance.now() - startPerf)}ms`)
}

setInterval(() => {
    fetch()
}, 1000)

@zhang-wenchao
Copy link

fix: denoland/deno#26263

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants