Live data from Hacker News

Asynchronous Python and Databases

techspot.zzzeek.org

31–40 of 76 posts

Re: Asynchronous Python and Databases

#31
post #12

So the basic take away seems to be: don't bother using async patterns for single, low latency connections to a server on your local network. For anything where you're dealing with thousands of connections from random Internet hosts, "just spawn a thread for it" does not cut it. If you take that approach, you're setting yourself up to be accidentally DoS'd at some point in the near future. Async, on the other hand, ha…

I'd want data. The system I work on does in fact spawn a thread to handle each and every connection and in fact each connection thread spawns numerous child threads to exploit available parallelism within the request. The code is fully blocking and linear and anyone can read it and see what it is doing. The mentioned system is one of the largest public networks services on earth.

I am very skeptical of the idea that you must not handle thousands of connections with a thread per connection. High tens of thousands of threads per core is the minimum level where I would start to worry.

Re: Asynchronous Python and Databases

#32
post #9

If you need that much performance out of Python, it's probably time to switch to Go. With Python, you still have the Global Interpreter Lock, even in PyPy. Multiple CPUs, which you probably have available, don't help.

The global interpreter lock does not apply to multiple processes. Web applications are embarrassingly parallel.

Re: Asynchronous Python and Databases

#33
post #7

I just want to note that asynchronous programming is analogous to cooperative multitasking, as used in the Windows 3.1 era. It seems, if we value low latency, that we should not pursue that route for the long term, or we should be very cautious about it. For tasks that are not purely I/O bound, its use is questionable.

I disagree. It is not analogous to cooperative multitasking, since Windows 3.1 dealt with different applications -- but asynchronous programming is targeting only a single (server) application. I also would add, that asynchronous implemented server applications are doing oftentimes better than systems that primarily rely on threading.

> but asynchronous programming is targeting only a single (server) application

As systems get more complex, this is not true anymore, because thinking otherwise would put the composability of the software at risk. Large software is typically built from many heterogeneous components.

> I also would add, that asynchronous implemented server applications are doing oftentimes better than systems that primarily rely on threading.

In the case of purely I/O bound applications, you may be right. Otherwise, it is a matter of finding the "sweet spot": just like bubble-sort is faster for certain applications than quicksort, does not mean it is the sort-routine we should be putting at the center of our frameworks, and build our software around.

Also note that asynchronously servicing N users, where each of the N services has a certain probability p>0 to "lock" the system for longer than expected, will increasingly become an unresponsive experience for increasing N.

Re: Asynchronous Python and Databases

#34
Note that the 'academic theorists' you cite would rather use an actor based system (and not events), and elsewhere in academia there's quite outspoken criticism of event-based systems[1] even for high-concurrency use cases. So, yes, threads have their problems, but event-based systems are not the panacea.

[1] http://static.usenix.org/publications/library/proceedings/ho...

Re: Asynchronous Python and Databases

#35
post #5

Earlier quoted context omitted.

I ran benchmarks for the app I mentioned. I don't have them on me because I no longer work for the company, but the database was the bottleneck on every request once we switched to PyPy. Again, I'm not saying your benchmarks are invalid, but the assumptions you make don't hold for all (or probably even the majority) of business web apps.

Anecdotally, I've seen quite a few Django apps using gevent "just because". If you don't need it, you're just incurring additional overhead for no gain (which is what the author is saying). There are legitimate usage cases for async patterns, but I have seen them used even in situations where they made things slower.

Well, what about people who run gunicorn + gevent workers?

Re: Asynchronous Python and Databases

#37
post #14

If you have a Python CRUD app, there are many steps you should take to speed up the app before parallelizing queries. The first couple that come to mind: - Caching. The 90-10 rule applies to most CRUD apps. Use varnish to get rid of some requests before they hit your webserver or make a redis/memcache LRU layer to prevent queries from hitting your database. - Shifting more work away from Python to the database. A sur…

> - Shifting more work away from Python to the database. A surprising number of apps don't do pagination properly.

This is very true. Get as much out of database before doing in python. Creation of objects such as new list is very expensive in Python, especially when you are dealing with large amount of data.Iterating over data just to do some aggregation that can be done in DB is slow and expensive. Cache the result later if you expect that to be useful.

Re: Asynchronous Python and Databases

#38
post #35
post #5

Earlier quoted context omitted.

Anecdotally, I've seen quite a few Django apps using gevent "just because". If you don't need it, you're just incurring additional overhead for no gain (which is what the author is saying). There are legitimate usage cases for async patterns, but I have seen them used even in situations where they made things slower.

Well, what about people who run gunicorn + gevent workers?

What about them?

Re: Asynchronous Python and Databases

#39
> In practice, you'll end up with so many "yield from" lines in your code that you're right back to "well, I guess I could context switch just about anywhere", which is the problem you were trying to avoid in the first place.

This is backwards, like when my Java colleague complained I was putting "final" in too many places. The point isn't the lines that contain "yield from". It's the lines that don't contain "yield from". You can make an explicit choice that you don't want context switches to happen on particular lines. In traditional multithreading you can kinda-sorta do this with mutexes - but it's less efficient and, more importantly, more error-prone.

> Database Code Handles Concurrency through ACID, Not In-Process Synchronization

Maybe. The problem is, not everything is (or should be) in the database. Even for CRUD webapps, we tend to end up needing a general-purpose programming language (otherwise you'd just write them in MS Access, no?) And so we need general-purpose language mechanisms for dealing with concurrency.

Post reply on HN