Skip to content

Conversation

@Reskov
Copy link
Contributor

@Reskov Reskov commented Apr 28, 2025

New asyncpg 0.30.0 fetchmany do the same stuff that we did in the queries test before, but much faster rather than calling fetchval in the loop. When queries count is low the results are the same, but when numbers of queries grow we can spot the difference.

After

 Queries: 20 for query
 wrk -H 'Host: tfb-server' -H 'Accept: application/json,text/html;q=0.9,application/xhtml+xml;q=0.9,application/xml;q=0.8,*/*;q=0.7' -H 'Connection: keep-alive' --latency -d 30 -c 32 --timeout 8 -t 6 "http://tfb-server:8080/queries/20"
---------------------------------------------------------
Running 30s test @ http://tfb-server:8080/queries/20
  6 threads and 32 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     2.81ms    4.52ms 122.69ms   89.94%
    Req/Sec     2.91k     1.79k    7.96k    65.83%
  Latency Distribution
     50%    1.21ms
     75%    3.17ms
     90%    7.36ms
     99%   18.76ms
  522369 requests in 30.06s, 389.82MB read
Requests/sec:  17379.58
Transfer/sec:     12.97MB

Before

---------------------------------------------------------
Running 30s test @ http://tfb-server:8080/queries/20
  6 threads and 32 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     4.54ms    7.84ms 161.52ms   96.87%
    Req/Sec     1.44k   445.63     2.97k    66.83%
  Latency Distribution
     50%    3.21ms
     75%    4.44ms
     90%    6.08ms
     99%   45.63ms
  258285 requests in 30.02s, 192.75MB read
Requests/sec:   8603.63
Transfer/sec:      6.42MB
STARTTIME 1745830666
ENDTIME 1745830696

@Reskov
Copy link
Contributor Author

Reskov commented Apr 28, 2025

@Dreamsorcerer please take a look and sorry for bothering you each time

@Dreamsorcerer
Copy link
Contributor

@Dreamsorcerer please take a look and sorry for bothering you each time

All good, I'm interested in any changes.

@msmith-techempower msmith-techempower merged commit d5c87a4 into TechEmpower:master Apr 28, 2025
4 checks passed
@Dreamsorcerer
Copy link
Contributor

@Reskov Have we tested with pypy yet?

@Reskov
Copy link
Contributor Author

Reskov commented May 10, 2025

@Dreamsorcerer no, I am personally not interested in pypy3, but I can add a test if you want. Secondly, we may try to cythonize entire app code.

Do you have any thoughts why update performance is much lower than fastapi app have.

https://www.techempower.com/benchmarks/#section=test&runid=6e3ad2d2-4acf-49cd-902a-286531ff3a67&f=zik0vz-zik0zj-zik0zj-zih7un-zik0zj-zik0zj-zik0zj-zik0zj-zik0zj-zik0zj-zik0zj-zik0zj-zik0zj-zik0zj-zik0zj-1ekf&test=query

image

@Dreamsorcerer
Copy link
Contributor

@Dreamsorcerer no, I am personally not interested in pypy3

Looks like FastAPI's fastest runs are on pypy3, so probably worth adding in. I think it's just a case of changing the docker image in the first line?

Secondly, we may try to cythonize entire app code.

I think that's a step too far and no longer comparing frameworks. At some point, it'd be good to compile everything under mypyc though, which could easily be adopted to all frameworks (it's probably not quite mature enough yet to work on a general application though).

litongjava pushed a commit to litongjava/FrameworkBenchmarks that referenced this pull request May 30, 2025
@Dreamsorcerer
Copy link
Contributor

Fastapi still seems to get better performance on the updates. I'm wondering if one or both of the sorted() calls actually speeds up the DB query?

Pypy also seems to be slower for aiohttp for some reason..

@Reskov
Copy link
Contributor Author

Reskov commented Jun 6, 2025

Yeah, also interesting that nginx performs better only on update. So probably the problem is high concurrency and we face locks on the database

P.S. about sort it is common technic I guess to avoid deadlock https://stackoverflow.com/questions/46366324/postgres-deadlocks-on-concurrent-upserts

https://www.postgresql.org/docs/current/explicit-locking.html#LOCKING-DEADLOCKS

In the example above, if both transactions had updated the rows in the same order, no deadlock would have occurred. One should also ensure that the first lock acquired on an object in a transaction is the most restrictive mode that will be needed for that object. If it is not feasible to verify this in advance, then deadlocks can be handled on-the-fly by retrying transactions that abort due to deadlocks.

@Reskov
Copy link
Contributor Author

Reskov commented Jun 6, 2025

@Dreamsorcerer
Copy link
Contributor

interestingly, looks like top performance framework are updating all rows at once.

I assumed that's what we were doing already, but maybe I'm not familiar enough with the DB functions.

@Reskov
Copy link
Contributor Author

Reskov commented Jun 6, 2025

@Dreamsorcerer not exactly I've prepared a draft here #9932

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

Successfully merging this pull request may close these issues.

3 participants