5 ms·
Using a non-blocking server with Python does not really make sense since most libraries in Python are blocking by nature and gevent only solves the most simple
by amix 16y ago
Using a non-blocking server with Python does not really make sense since most libraries in Python are blocking by nature and gevent only solves the most simple conversions by monkey patching (and like the author notes this is very error prone).
If you want to use non-blocking in Python then using something like Twisted is an option since Twisted implements most things in an non-blocking way, but Twisted hasn't really gained that much traction in the many years of its existence.
So yes if you do a hello world benchmark then you get a 4x speed improvement, but if you do any library calls (such as doing a MySQL query) you will get decreased perfomance since the MySQL Python library is blocking (and most other libraries are blocking as well)...
- denik 16y agogevent runs most of the protocol implementations written on top of standard socket and ssl modules. For example, pure Python mysql-connector works fine with gevent. There's also a mysql driver for gevent implemented as an extension: http://github.com/mthurlin/gevent-MySQL http://github.com/mthurlin/gevent-MySQL
- suhail 16y agoI wouldn't recommend mysql-connector in production... A while back we avoided gevent because of this but used eventlet instead because they had a native MySQL patched driver. Performance on the pure connector was just too bad.
- denik 16y agoI mentioned mysql-connector as an example of a complex enough library that runs with gevent via monkey patching (in reply to "gevent only solves the most simple conversions by monkey patching", which is wrong). Have you tried gevent-MySQL? It's written in Cython and as far as I know is fast.
- levigross 16y agoThe advantage here is the usage of Libevent which makes it only listen when a eventlet sends back a message. It's essentially using the same tech (event wise) as NGINX. Because it's using event's it has not blocking IO. But is limited when the tasks are CPU bound
- deleted 16y ago[deleted]
- amix 16y agoEverything in nginx is non-blocking, almost nothing in Python is - this is a huge difference and this can be fatal for perfomance if all your libraries aren't non-blocking. An example: let's say you are executing an expensive query to MySQL in a non-blocking server and you are using the most popular libraries - - The problem with this is that this query will block your whole server and you won't be able to process any requests while this query is performed. If you want to take advantage of non-blocking then all your IO calls have to be non-blocking (like in node.js), else you don't gain much perfomance other than perfomance on hello world benchmarks - - and you may risk to decrease perfomance critically if _any_ of your IO calls are expensive. Gevent tries to solve this by monkey patching, but this solution is partial and it does not work with modules that use C extensions such as pylibmc (the fastest memcache library for Python) or MySQL-python (the most mature MySQL library for Python). I would love to see Python move into a non-blocking direction, but for this to happen then a huge change needs to be made and anything IO/network related has to be non-blocking... Which basically is Twisted and Twisted isn't that used, so I doubt the general Python community will move that much in the non-blocking direction.
- suhail 16y agoSure performance is worse but still better since threads yield while blocking on IO to other threads. You're doing as much work as possible and bottled only by CPU in this case.
- deleted 16y ago[deleted]
- andrewgodwin 16y agoThere's also eventlet, which gevent was (essentially) forked from - it has the advantage of having both libevent backends (like gevent, and aren't threadsafe due to libevent) and threadsafe backends too (not that I have much call to use threads while using a greenthread-based framework).
- BarkMore 16y agoUsing a non-blocking server with Python does make sense if you use non-blocking code for the things that take a long time. Here's an example: a server takes 400ms to handle a request. Of that time, 300ms is spent waiting for an HTTP response to an external service. The other 100ms is spent accessing the local database and other blocking operations. If the server does not block waiting for the HTTP response, then an instance of the server can handle 10 requests a second (1000ms / (400ms - 300ms)). If the server does block, then an instance of the server can handle 2.5 requests per second (1000ms / 400ms). An instance of the non-blocking server has 4x the throughput of the blocking server.
- amix 16y agoMy argument is that most things that potentially take a lot of time are blocking by default in Python, which makes it a bad fit for making non-blocking servers... I am not arguing that blocking servers have better perfomance than non-blocking servers...
- BarkMore 16y agoI am arguing that a small number of things take a long time in a web server. Can you give some examples of things that potentially take a long time in a web server that are not already covered by Tornado (http client, long polling)?
- amix 16y agoDatabase drivers (Redis, MySQL, Tokyo Tyrant etc.) and a bad query/overheated database server can easily take over 1 sec execution, which would basically stall your servers each time such a query is run. File handling and system calls are blocking in Python. E.g. if your system call is expensive - say you are processing an image via imagemagick, very common for most web applications, then it will block your server.
- BarkMore 16y agoBlocking for short periods of time is fine if you run more than one instance of the python application per core. If database database access is taking more than a second, then I recommend fixing that problem first.
- dcreemer 16y agoThat's simply not true. Yes you have to be smart and know which Python libraries can block (typically those that do their network calls in C, or those that do disk I/O). In practice however this is not a difficult task. After writing several major projects with gevent, all of which make several thousands of network requests per minute, I have to say that it's a pleasure to use. Not magic, but very useful. I have written non-trivial apps with Twisted, and dabbled with Tornado. Gevent avoids all of the "inside out" coding in an elegant way.