<story><title>12 requests per second: A realistic look at Python web frameworks</title><url>https://suade.org/dev/12-requests-per-second-with-python/</url></story><parent_chain><item><author>stevenjohns</author><text>There is lots of truth to this. Some ORMs like Django perform joins in very unsuspecting ways.&lt;p&gt;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&amp;#x27;s less known that the id is immediately available by just doing `book.user_id` instead.&lt;p&gt;I&amp;#x27;ve spent time optimising things like text searches down from 2000+ queries to about ~4, and one of the more noticeable things to me isn&amp;#x27;t actually the number of joins, rather the SELECT&amp;#x27;s that take place. Many of these ORMs do a SELECT * unless you explicitly tell them to otherwise, and when dealing with large-ish datasets or on models that have large text fields this translates into significant time taken to &lt;i&gt;serialise&lt;/i&gt; these attributes. So you can optimise the query and still have it take a long time until you realise that limiting the initial `SELECT` parameter is probably more efficient than limiting the number of joins.</text></item><item><author>imperio59</author><text>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&amp;#x27;s expensive).&lt;p&gt;Sure, the framework matters at very large scale and the benefits from optimizing the framework become large when you&amp;#x27;re doing millions of requests a second over many thousands of servers because it can help reduce baseline cost of running the service.&lt;p&gt;But I agree with the author&amp;#x27;s main point which seems to be that framework performance is pretty meaningless when comparing frameworks if you&amp;#x27;re just starting on a new project. Focus on making a product people wanna actually use first. If you&amp;#x27;re lucky enough to get to scale you can work about optimizing it then.</text></item></parent_chain><comment><author>gregmac</author><text>The most insidious part about misusing ORMs is it&amp;#x27;s often not visible for a while. Modern DBMSs on modern hardware are &lt;i&gt;crazy fast&lt;/i&gt;, 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&amp;#x27;s hard  to distinguish between the real problem and &amp;quot;I guess we&amp;#x27;re just handling more requests per second&amp;quot;.&lt;p&gt;I personally love tools like Miniprofiler [1] for this (though maybe there&amp;#x27;s something better today, it&amp;#x27;s been a while since I&amp;#x27;ve worked on that type of thing). It&amp;#x27;s a constant and accessible way to keep an eye on what goes into each request, and I&amp;#x27;ve caught many of those bad queries before they were problems by using it (eg: &amp;quot;WTF, why did it take 9 queries and 250ms to grab what looks to be a single row from a single table?!&amp;quot;).&lt;p&gt;[1] &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;miniprofiler.com&amp;#x2F;&quot; rel=&quot;nofollow&quot;&gt;https:&amp;#x2F;&amp;#x2F;miniprofiler.com&amp;#x2F;&lt;/a&gt;</text></comment>
<story><title>12 requests per second: A realistic look at Python web frameworks</title><url>https://suade.org/dev/12-requests-per-second-with-python/</url></story><parent_chain><item><author>stevenjohns</author><text>There is lots of truth to this. Some ORMs like Django perform joins in very unsuspecting ways.&lt;p&gt;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&amp;#x27;s less known that the id is immediately available by just doing `book.user_id` instead.&lt;p&gt;I&amp;#x27;ve spent time optimising things like text searches down from 2000+ queries to about ~4, and one of the more noticeable things to me isn&amp;#x27;t actually the number of joins, rather the SELECT&amp;#x27;s that take place. Many of these ORMs do a SELECT * unless you explicitly tell them to otherwise, and when dealing with large-ish datasets or on models that have large text fields this translates into significant time taken to &lt;i&gt;serialise&lt;/i&gt; these attributes. So you can optimise the query and still have it take a long time until you realise that limiting the initial `SELECT` parameter is probably more efficient than limiting the number of joins.</text></item><item><author>imperio59</author><text>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&amp;#x27;s expensive).&lt;p&gt;Sure, the framework matters at very large scale and the benefits from optimizing the framework become large when you&amp;#x27;re doing millions of requests a second over many thousands of servers because it can help reduce baseline cost of running the service.&lt;p&gt;But I agree with the author&amp;#x27;s main point which seems to be that framework performance is pretty meaningless when comparing frameworks if you&amp;#x27;re just starting on a new project. Focus on making a product people wanna actually use first. If you&amp;#x27;re lucky enough to get to scale you can work about optimizing it then.</text></item></parent_chain><comment><author>paulmd</author><text>&amp;gt; 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&amp;#x27;s less known that the id is immediately available by just doing `book.user_id` instead.&lt;p&gt;Hibernate (on Java) at least optimizes this specific use-case.  At first, accessing a lazy-loaded property-object will give you a &amp;quot;proxy&amp;quot; and you can access the ID without incurring a database load (since it knows that anyway).  And when doing a query, the object won&amp;#x27;t be joined when requesting book.user.id unless it needs to be (like you have some other WHERE clause that requires an actual join on that row).</text></comment>