Live data from Hacker News

Write Fast Apps Using Async Python 3.6 and Redis

eng.paxos.com

111–120 of 134 posts

Re: Write Fast Apps Using Async Python 3.6 and Redis

#111
post #97
post #94

Earlier quoted context omitted.

> it becomes less and less uncommon to have more than one query per page. I said transaction, not query. A database transaction is on a single connection at a time and queries are performed via the transaction serially.

In many non trivial cases I tend to find that I have to query several different databases to render a single page.

depending on the latency of those database connections I've argued in the past that the overhead of adding asyncio context switching and boilerplate is more expensive than just hitting the two or three databases in serial (and if your web request is having to hit dozens of DB sources to serve one request, I think you've already lost the performance game :) ). When your one web request is contending with many other concurrent web requests in any case, doing the DB calls in serial just lets the CPU attend to other requests.

Re: Write Fast Apps Using Async Python 3.6 and Redis

#112
post #98
post #94

Earlier quoted context omitted.

> it becomes less and less uncommon to have more than one query per page. I said transaction, not query. A database transaction is on a single connection at a time and queries are performed via the transaction serially.

not everything is transaction centric. and also before I make a transaction I mostly fetch various stuff before and sometimes after. and also my count example, it just makes no sense to have the count and the list data called inside a transaction (ok there are cases, but these are way more rare, because mostly It's not to bad to give users a wrong count, you don't need strict Serializability)

see my edit at https://news.ycombinator.com/item?id=14218862 where I propose a challenge to show that it's more efficient to use ten relational database connections for a request that needs to run ten small queries, vs running ten queries on a single DB connection.

Re: Write Fast Apps Using Async Python 3.6 and Redis

#113
post #110

Earlier quoted context omitted.

> I said transaction, not query. A database transaction is on a single connection at a time and queries are performed via the transaction serially. Unless you're doing e-commerce or banking sites, that's far less common that non-transaction requests.

unless you're using MyISAM or something like that, all your queries are in transactions. edit: also, I'd challenge you to prove that for a web request that needs to make ten read queries to a relational database, from Python, that you can get better performance by opening up ten separate database connections (or from a pool) and running one query in each, bundled into the async construct of your choice and then mergi…

It's not uncommon to have ~20 pooled connections lying around. Maybe it's not that frequently used in Python or PHP, but in various other platforms, that's just the normal case.

At least in Java, C#, Golang. And even psycopg2 offers a Pooling Abstraction (I guess it's not used in Django, but SQLAlchemy offers that aswell) But of course running a blocking driver atop a non-blocking framework does not give the best performance.

However just challenging it without proof is not really that useful.

Also some workloads are better for Threaded Servers while others are better in Async Fashion, it's also highly unlikely that just wrapping your Database connection in a Async function that it will be faster or better suited for a async workload. If you are not non-blocking from the ground up you will still carry a lot of overhead around.

Re: Write Fast Apps Using Async Python 3.6 and Redis

#114
post #110

Earlier quoted context omitted.

> I said transaction, not query. A database transaction is on a single connection at a time and queries are performed via the transaction serially. Unless you're doing e-commerce or banking sites, that's far less common that non-transaction requests.

unless you're using MyISAM or something like that, all your queries are in transactions. edit: also, I'd challenge you to prove that for a web request that needs to make ten read queries to a relational database, from Python, that you can get better performance by opening up ten separate database connections (or from a pool) and running one query in each, bundled into the async construct of your choice and then mergi…

Sorry - I wasn't clear enough. Who says it's one single relational database? And besides, like I mention, it's often not relational database queries but a service calls (think microservice architectures, for example). Or both!

Anyway, I respect your position that yes, for the average user, throwing a bunch of "async" in there isn't going to make their code faster, and it's just cargo cult programming. And yes, there is some tradeoff curve where sometimes, for a small benefit, it's not worth the effort to worry about it, as with all things. But it's just a tough sell to argue that no one should need this :-)

More and more often today, the backend serves as glue between frontend clients and a horde of services / data systems. This is often an I/O heavy workload (wait while I make a request, wait for a response, wait while I download x10). This kind of workload is ripe for speeding up with async. That's all I'm saying!

Re: Write Fast Apps Using Async Python 3.6 and Redis

#115
post #63

Earlier quoted context omitted.

I'm glad you said this. There's an async cargo cult going on, where every service must be written in "performant" async code, without knowing the actual resource and load requirements of an application. From the last benchmark I ran [1] async IO was insignificantly faster than thread-per-connection blocking IO in terms of latency, and marginally faster only after we hit a large number of clients. Async IO doesn't nec…

const users = await getUsers(); const tweets = await getTweets(users); console.log(tweets); Is async code really harder to read?

In your example the async code doesn't really help anything though - the next statement has to wait for the response from the previous one before continuing.

In your example you'd probably want to be using Promise.all to run two IO operations simultaneously.

Re: Write Fast Apps Using Async Python 3.6 and Redis

#116
post #103

> Write Fast Apps Using Async Python When working with Python and Ruby I find 80ms responses acceptable. In very optimized situations (no framework) this can do down to 20ms. Now I've used some Haskell, OCaml and Go and I have learned that they can typically respond in In both cases this includes querying the db several times (db queries usually take less then a millisecond, Redis shall be quite similar to the extend…

You can get 2-3 ms response time (sans network) with any of Django, Flask and Pyramid. Database queries tend to eat a lot, esp. if the queries are bad (long wait in the DBMS or post-filtering in Python/whichever); sometimes ORMs can eat a fair bit as well. But it's fairly rare to get that low, most pages for me (that I cared about) will take 10-30 ms. Using the correct tools and the right approach is fruitful as always.

Re: Write Fast Apps Using Async Python 3.6 and Redis

#117
post #116
post #103

> Write Fast Apps Using Async Python When working with Python and Ruby I find 80ms responses acceptable. In very optimized situations (no framework) this can do down to 20ms. Now I've used some Haskell, OCaml and Go and I have learned that they can typically respond in In both cases this includes querying the db several times (db queries usually take less then a millisecond, Redis shall be quite similar to the extend…

You can get 2-3 ms response time (sans network) with any of Django, Flask and Pyramid. Database queries tend to eat a lot, esp. if the queries are bad (long wait in the DBMS or post-filtering in Python/whichever); sometimes ORMs can eat a fair bit as well. But it's fairly rare to get that low, most pages for me (that I cared about) will take 10-30 ms. Using the correct tools and the right approach is fruitful as alwa…

> You can get 2-3 ms response time (sans network) with any of Django, Flask and Pyramid.

Wow, never managed to do that. Maybe I have to try it again (last time checked on Django was some years ago).

Re: Write Fast Apps Using Async Python 3.6 and Redis

#119
post #3

We've just recently started using Sanic[0] paired with Redis to great effect for a very high throughput web service. It also uses Python 3 asyncio/uvloop at its core. So far very happy with it. [0] https://github.com/channelcat/sanic

I have never found a good example of a Python web server that provides some mechanism for statefulness. Is it just fundamentally not possible to have shared state among requests handled by the threads of a process? Sanic's examples seem to be the same as Flask's: self-contained function calls attached to endpoints. I keep hitting a wall with Python when I want to do something like: 1. subscribe to a websocket connect…

I am a little confused here. What's keeping you from storing your state in a global variable?

Re: Write Fast Apps Using Async Python 3.6 and Redis

#120
post #115

Earlier quoted context omitted.

const users = await getUsers(); const tweets = await getTweets(users); console.log(tweets); Is async code really harder to read?

In your example the async code doesn't really help anything though - the next statement has to wait for the response from the previous one before continuing. In your example you'd probably want to be using Promise.all to run two IO operations simultaneously.

The next statement has to wait, but the runtime can yield to another waiting async task so you aren't blocking the total throughput of your program (assuming it's async-all-the-way-down).

The benefits are generally larger-scale than a single method.

Post reply on HN