-
Notifications
You must be signed in to change notification settings - Fork 267
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
Reuse connections between requests with Postgres #3030
Comments
There may be a concern around trying to use a connection that is in an unknown state. We should investigate whether the Rust PG library manages a connection pool for us |
If we don't find a good postgres pooling library we can probably use a generic pool and just be sure to |
Found an Actix sample (https://github.com/actix/examples/blob/master/databases/postgres/src/main.rs) which uses |
@kate-goldenring @lann deadpool offers options for how connections get reused, from "fast" (claims to be a safe choice unless you have special needs) to https://docs.rs/deadpool-postgres/latest/deadpool_postgres/enum.RecyclingMethod.html How comfortable are folks with the different levels? I haven't quantified the performance tradeoffs, so I appreciate that I'm not giving you much to go on as regards the consequences. |
Kicking the tyres with this. Unscientific test with a trivial select from a one-row table on localhost. Pool size 4:
(A pool size of 16 made only a "within one standard deviation" difference in this case. I couldn't increase the number of connections much more because Spin started falling over with component instance limits.) For comparison, Spin 3.1.2:
with the 5xx errors logging |
The perf figures get dramatically different when I make the database interaction a fraction more complex. Here's one where, with my one line table, I do an INSERT, a SELECT, and then a DELETE of the inserted row. I did the comparison using 20 bombardier connections (so as not to cause Spin 3.1.2 grief) so these aren't directly comparable to above.
(A pool size of 128 was a marginal improvement over 64.) When I whomped the big pool with 200 bombardier connections I got a lot of "too many clients" errors from the database. I tried bombarding at 100 connections. Spin 3.1.2 was wobbly and I got the occasional "too many clients".
A 128 pool was again better but still within a standard deviation. The performance with 64 was pretty variable - that whopping SD is no lie, but the run I showed seems around in the middle. I tried using deadpool's I don't really know how to interpret any of this in terms of making choices about the pool size, or if it's even meaningful with relatively few tests on a machine with other stuff going on (you know who you are, rust-analyser). Maybe we should punt to the user/admin but that feels a bit lazy, and we still need a decent default. I realise that what data I have is pretty scattershot but I'd welcome guidance from pooling nerds, even if only pointers to better tests to run. |
I should probably stress that all these numbers were for a single local database. So there was only one pool in operation. I haven't yet tested with multiple databases, or with off-machine network latency. |
Tying up what i see as the summary from above
It seems like with the pool, the same connection may not be being used for the 3 operations. Are they all done in one transaction or in 3 separate ones? |
@kate-goldenring I would add that I ran test case C first with 20 connections (deadpool slower) and then with 100 connections (deadpool faster and more stable). I'm not sure what "Fast" refers to in your comment - if it relates to connection recycling then these were done as Clean (I tried Fast but it wasn't faster). I didn't use transactions but each operation within a request was done on the same Spin connection. The code I used was:
On the Spin side, each Postgres connection string is associated with a pool (so all requests used the same pool). The object created in I'd be delighted if you have guidance on better ways to evaluate this - I'm flailing a bit I'm afraid. |
The Postgres host component creates a client during calls to
open_connection
this client can then be reused across all database interactions within that request.Ideally, connections should be shared between requests, with clients cached.
The text was updated successfully, but these errors were encountered: