Live data from Hacker News

12 requests per second: A realistic look at Python web frameworks

suade.org

171–180 of 239 posts

Re: 12 requests per second: A realistic look at Python web frameworks

#171

Related to ORMs/queries/performance, I have found the following combination really good: * aiosql[0] to write raw SQL queries and having them available as python functions (discussed in [1]) * asyncpg[2] if you are using Postgres * Map asyncpg/aiosql results to Pydantic[3] models * FastAPI[4] Pydantic models become the "source of truth" inside the app, they are designed as a copy of the DB schema, then functions rece…

Thank you for sharing this stack! I'm a Pythonista at heart, recently was trying RxDB + TypeScript, and I was thinking hmm I'll bet I could do something with postgres and Pydantic.

Re: 12 requests per second: A realistic look at Python web frameworks

#172

C#/ASP.NET is the fastest web framework now: https://www.techempower.com/benchmarks/#section=test&runid=8... 7.000.000 requests per second Even GO can only achieve 4.500.000 million requests per secnod being a low-level language, in opposite to high-level C#.

Hmm no they have the same speed with gnet ( Go ): https://www.techempower.com/benchmarks/#hw=ph&test=plaintext 7M req/sec both of them.

( all those benchmarks are sort of useless anyway )

Re: 12 requests per second: A realistic look at Python web frameworks

#173
post #122

Earlier quoted context omitted.

The programmer also already had the value in book.user_id but still chose to ask the ORM to fetch all of .user so they could get .id from there instead. And they might then afterward call .name on it as well, and there would be no further queries, because the ORM has already been asked to fetch all fields of .user - so it might in fact have been sensible to fetch all of .user if so. The query builder cannot know whet…

Perhaps i'm a bit odd, but when I'm going to lean on an ORM to do things I expect it to actually do them. I expect that foo.user_id does not exist, because that representation has been transformed into an object. foo.user.id should be the only viable reference to the id. foo.user.id should return the value it already knows, any other property access i would expect will do the equiv of `select * from ...` if the objec…

> I expect that foo.user_id does not exist, because that representation has been transformed into an object.

Or you can just consider user_id to be a reference pointer that is part of foo, while user.id is an attribute of user. Totally different things and I am glad that the distinction is there.

Re: 12 requests per second: A realistic look at Python web frameworks

#174

Earlier quoted context omitted.

There is lots of truth to this. Some ORMs like Django perform joins in very unsuspecting ways. A simple example is, say, foreign keys. Trying to access the foreign key of an object by doing `book.user.id` does an additional query for the user table to get the ID. It's less known that the id is immediately available by just doing `book.user_id` instead. I've spent time optimising things like text searches down from 20…

The most insidious part about misusing ORMs is it's often not visible for a while. Modern DBMSs on modern hardware are crazy fast , so when you have only a few tens or hundreds of thousand rows in your table, those inefficient and pointless ORM queries are just not noticeable because you still get sub-second response times. As your database grows, the site begins to gets slower and slower, but it's hard to distinguis…

To be fair this is a problem inherent to databases in general. You can have hand written queries that perform badly due to structure or query frequency as well which are not apparent until the dataset grows. The ORM should make it easier to rectify such situations (eg drop in an eager loading directive) vs having to restructure hand-written routines for similar effects.

Re: 12 requests per second: A realistic look at Python web frameworks

#175
post #167

Why is it so? I've got 100K requests per sec with PHP easily [1] [1] https://github.com/gotzmann/comet

"Blazing fast with 100K HTTP requests per second and ~0.1 ms latency on commodity cloud hardware"

Ok what's the secret sauce and downsides? Because as far as I know there's no way to cheat with PHP like C# did here:

https://github.com/TechEmpower/FrameworkBenchmarks/blob/mast...

Re: 12 requests per second: A realistic look at Python web frameworks

#176
post #40

Earlier quoted context omitted.

That's a nice benefit of using async ORMs (not yet available in django), the db calls are explicit!

You can also commit to always use .values() in django. That makes it error out when you access non-prefetched entities

also, values is awesome for returning your models as dicts when that's all you need most of the time, avoiding all the overhead of objects

Re: 12 requests per second: A realistic look at Python web frameworks

#177

My experience doing perf optimizations in real world systems with many many people writing code to the same app is a lot of inefficiencies happen due to over fetching data, inefficiencies caused by naively using the ORM without understanding the underlying cost of the query, and lack of actual profiling to find where the actual bottlenecks are (usually people writing dumb code without realizing it's expensive). Sure,…

There is lots of truth to this. Some ORMs like Django perform joins in very unsuspecting ways. A simple example is, say, foreign keys. Trying to access the foreign key of an object by doing `book.user.id` does an additional query for the user table to get the ID. It's less known that the id is immediately available by just doing `book.user_id` instead. I've spent time optimising things like text searches down from 20…

> ...in very unsuspecting ways

> Trying to access the foreign key of an object by doing `book.user.id` does an additional query for the user table to get the ID. It's less known that the id is immediately available by just doing `book.user_id` instead.

But that's not really unsuspecting. `book.user` is asking for the user table, `book.user_id` is not. Those two things are not identical even though they return the same value.

Re: 12 requests per second: A realistic look at Python web frameworks

#178

My experience doing perf optimizations in real world systems with many many people writing code to the same app is a lot of inefficiencies happen due to over fetching data, inefficiencies caused by naively using the ORM without understanding the underlying cost of the query, and lack of actual profiling to find where the actual bottlenecks are (usually people writing dumb code without realizing it's expensive). Sure,…

I increasingly lean towards plain SQL over ORMs. It requires greater familiarity with SQL but I prefer that over greater familiarity with ORM-specific syntax that doesn’t translate across frameworks or languages. In addition, you can prototype new queries and profile existing queries in the database and copy-paste directly into your code.

I like ORMs for doing the things for me like making objects and converting dates and other data to DB ready form and vice versa. I do not like them querying. The premise with ORMs is that you should be able to query pretty much anything easily. The reality is that almost all of the time you are doing something you don't have many distinct queries. You have a few reads and writes that you have to do. Things that are easily done in SQL with full expressiveness and efficiency.

So now my pattern is to use for example ActiveModel in Ruby for the models, but not ActiveRecord for the persistence part.

Re: 12 requests per second: A realistic look at Python web frameworks

#179
post #92

Earlier quoted context omitted.

C# is only at number 3 in your list. Both Java and Rust are above it in the list. It's also a very "artificial" benchmark and real world code will give different results (if you have static content, just put it in a CDN and don't worry) Other benchmarks from the same site: - JSON Serialization: C# is number 34 - Single query: C# is number 23 - Fortunes: C# is number 7

It needs to be emphasized how artificial these benchmarks really are. Here is the source for the Fortunes C# benchmark: https://github.com/TechEmpower/FrameworkBenchmarks/blob/mast... There's no routing or templating, it just writes a bunch of strings. No one would build an actual web app this way. The only C# benchmarks that are remotely realistic are the mvc variants, starting with aspcore-mvc-ado-pg at number 79.

https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Proj...

Routing is required, but generally the rules allow things to be "reasonable" and "acceptable", which lets all these weird implementations through.

Honestly, they should remove the "Implementation approach" column, because basically every implementation is marked as "realistic", making it meaningless.

Re: 12 requests per second: A realistic look at Python web frameworks

#180
post #175
post #167

Why is it so? I've got 100K requests per sec with PHP easily [1] [1] https://github.com/gotzmann/comet

"Blazing fast with 100K HTTP requests per second and ~0.1 ms latency on commodity cloud hardware" Ok what's the secret sauce and downsides? Because as far as I know there's no way to cheat with PHP like C# did here: https://github.com/TechEmpower/FrameworkBenchmarks/blob/mast...

The most important part is Workerman and its efficient network arhitecture based on libevent. The other part is efficient DB drivers. Thats why Comet ranks much higher than Go / NodeJS / Python frameworks in DB higloaded test:

https://www.techempower.com/benchmarks/#section=data-r20&hw=...

Post reply on HN