I have an existing Django app. What do I need to do to have it run on
gevent? Does it require re-write?
One of my biggest issue is database interaction. Some of my pages
involve 10 or so SQL queries. Right now they all have to be run
sequentially. Can gevent make them run concurrently? Normally a
database call is blocking, so not sure if it would work here.
Thanks.
On Sat, Mar 20, 2010 at 1:49 AM, Andy <selfor...@gmail.com> wrote:
> I stumbled upon gevent. It looks very interesting. And I want to learn
> more about it.
>
> I have an existing Django app. What do I need to do to have it run on
> gevent? Does it require re-write?
You should monkey patch threading and socket modules to work with greenlets.
To do that, put
from gevent import monkey; monkey.patch_all()
before importing everything else.
Here's an example Django app powered by gevent:
http://blog.gevent.org/2009/10/10/simpler-long-polling-with-django-and-gevent/
Monkey patching socket module makes network-using parts of Django,
like sending an email
or validating an URL through urllib2, cooperative (= blocking only the
current greenlet and letting
others run). No rewriting of your code is needed.
Monkey patching threading makes threading.threadlocal into
greenlet-local. Django uses a threadlocal
variable to store the database connections, so each Django sees each
greenlet as a thread and
runs it isolated from others.
>
> One of my biggest issue is database interaction. Some of my pages
> involve 10 or so SQL queries. Right now they all have to be run
> sequentially. Can gevent make them run concurrently? Normally a
> database call is blocking, so not sure if it would work here.
If the database driver is written in Python, then monkey patching
socket (and ssl if that's used) module
will make the database queries cooperative (that is, asynchronous
under the hood).
You can use gevent.spawn() to run them concurrently and join() to
collect results, for example.
However, you should measure that it really helps, as the queries might
still be run sequentially
in the server.
I've seen reports of using pg8000 (postgreSQL) and mysql-connector
with gevent successfully.
If the database driver is written in C, then it'll block the whole
interpreter. If you think you need
to work around that, you can
1. fork multiple wsgi server worker processes.
2. use threadpool for database connections.
Rather than implementing forking yourself you might want to look at
gunicorn which has some support for gevent in the trunk
(http://github.com/benoitc/gunicorn). It's still in the development,
but it's something worth following.
As for threadpool for gevent, there's one in the development as well,
http://bitbucket.org/denis/gevent-playground/src/
Cheers,
Denis.
> You should monkey patch threading and socket modules to work with greenlets.
>
> To do that, put
>
> from gevent import monkey; monkey.patch_all()
>
> before importing everything else.
>
> Here's an example Django app powered by gevent:http://blog.gevent.org/2009/10/10/simpler-long-polling-with-django-an...
>
> Monkey patching socket module makes network-using parts of Django,
> like sending an email
> or validating an URL through urllib2, cooperative (= blocking only the
> current greenlet and letting
> others run). No rewriting of your code is needed.
>
> Monkey patching threading makes threading.threadlocal into
> greenlet-local. Django uses a threadlocal
> variable to store the database connections, so each Django sees each
> greenlet as a thread and
> runs it isolated from others.
Where do I put the "from gevent import monkey; monkey.patch_all()"
statements? In my django project's settings.py?
I did see any monkey patching in the example you provided (http://
bitbucket.org/denis/gevent/src/tip/examples/webchat/chat/views.py). So
I'm a bit confused.
>
> > One of my biggest issue is database interaction. Some of my pages
> > involve 10 or so SQL queries. Right now they all have to be run
> > sequentially. Can gevent make them run concurrently? Normally a
> > database call is blocking, so not sure if it would work here.
>
> If the database driver is written in Python, then monkey patching
> socket (and ssl if that's used) module
> will make the database queries cooperative (that is, asynchronous
> under the hood).
> You can use gevent.spawn() to run them concurrently and join() to
> collect results, for example.
> However, you should measure that it really helps, as the queries might
> still be run sequentially
> in the server.
> I've seen reports of using pg8000 (postgreSQL) and mysql-connector
> with gevent successfully.
How do I use gevent.spawn() to run queries concurrently and join() to
collect results?
Right now all my database interactions are done through Django's ORM.
Not sure how spawn() & join() would fit in with the ORM.
Is there any code example that I can look at?
Thanks.
> If the database driver is written in C, then it'll block the whole
> interpreter. If you think you need
> to work around that, you can
> 1. fork multiple wsgi server worker processes.
> 2. use threadpool for database connections.
>
> Rather than implementing forking yourself you might want to look at
> gunicorn which has some support for gevent in the trunk
> (http://github.com/benoitc/gunicorn). It's still in the development,
> but it's something worth following.
>
> As for threadpool for gevent, there's one in the development as well,http://bitbucket.org/denis/gevent-playground/src/
Between using pure python driver and C driver+threadpools, is there a
"recommended" way? What are the pros and cons?
Thanks!
Monkey patching is process-global, so it's done before the server is run:
http://bitbucket.org/denis/gevent/src/45defea59ee8/examples/webchat/run.py
> Is there any code example that I can look at?
There are examples in the distribution:
http://bitbucket.org/denis/gevent/src/tip/examples/
In particular, this example:
http://bitbucket.org/denis/gevent/src/tip/examples/concurrent_download.py
shows how to run a few jobs concurrently and collect their results.
On Mar 25, 5:45 pm, Denis Bilenko <denis.bile...@gmail.com> wrote:
> > Is there any code example that I can look at?
>
> There are examples in the distribution:http://bitbucket.org/denis/gevent/src/tip/examples/
> In particular, this example:http://bitbucket.org/denis/gevent/src/tip/examples/concurrent_downloa...
> shows how to run a few jobs concurrently and collect their results.
So for every ORM operation that I want to run concurrently (save(),
delete(), QuerySet ops) I'd need to spawn a new greenlet to run it in?
That'd mean modifying existing application code then.
Is there any way to do this in a way that's transparent to the
application?
Thanks