Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gevent vs gevent_wsgi vs gevent_pywsgi workers #305

Closed
gsakkis opened this issue Feb 25, 2012 · 6 comments

Comments

Projects
None yet
4 participants
@gsakkis
Copy link

commented Feb 25, 2012

What's the relation of the (apparently undocumented) gevent_wsgi and gevent_pywsgi to the "plain" gevent worker type?

@benoitc

This comment has been minimized.

Copy link
Owner

commented Feb 25, 2012

gevent worker is our own worker using our wsgi parser, while otheres are gevent parsers.

@benoitc benoitc closed this Feb 25, 2012

@JeremyLoy

This comment has been minimized.

Copy link

commented Mar 2, 2019

Sorry to bump a 7 year old issue, but I was recently stuck with this same question for about a week.

I think that better documentation should be made for these 3 worker types.

Short summary of the week: I was experiencing identical performance for the sync and gevent workers, which was really confounding me. After looking at the source code, I discovered the gevent_pywsgi type which dramatically increased my performance.

Just curious, what is the purpose of the gevent worker option?

@tilgovi

This comment has been minimized.

Copy link
Collaborator

commented Mar 4, 2019

gevent_pywsgi and gevent_wsgi are the same. Names provided for backward compatibility. We could deprecate and remove one to make it slightly less confusing.

The rest is as described in the comment above. The regular gevent uses our parser code, while _wsgi uses one from Gevent.

If you find that gevent_pywsgi increases performance, that would not be a surprise. However, if you find identical performance between sync and gevent then it seems like you are not getting much benefit from gevent itself and therefore the only speed you get from gevent_pywsgi is from the parsing code.

You may want to try the gevent worker until you figure out the bottleneck, and whether you need asynchronous workers at all. Also, maybe you can say more about what you mean by performance: throughput (requests per second), latency (minimum), latency (average), etc. The sync and gevent workers are different.

Just curious, what is the purpose of the gevent worker option?

To patch the blocking I/O functions of the standard library to use the gevent hub and handle concurrent requests in greenlets. If you need to handle a high volume of concurrent requests and your application performs a lot of waiting on I/O (database, streaming responses, upstream requests, etc) then gevent can be a good choice.

@JeremyLoy

This comment has been minimized.

Copy link

commented Mar 5, 2019

@tilgovi here is a recent stack overflow I made regarding this issue

I was looking to improve throughput on a basic Flask hello world, and could not get above 125RPS with either the sync or gevent worker type.

Could you clarify the following for me? I'm still a bit confused.:

The regular gevent uses our parser code

What do you mean by parser?

In addition, looking at the source code of Gunicorn it seems that with -k gevent, the gevent.server.StreamServer is type is used, and with -k gevent_pywsgi, the gevent.pywsgi.WSGIServer type is used.

@tilgovi

This comment has been minimized.

Copy link
Collaborator

commented Mar 5, 2019

A basic hello world application is unlikely to see any performance improvement from gevent, especially if the benchmark is run locally or on a high performance network. The reason for this is that gevent only switches greenlets when performing I/O operations that would block. If you can receive the entire HTTP request in a single recv() call and respond with a single send() call, you are more or less doing what the sync worker is doing. The benefit of gevent is when your application has to wait on slow connections or upstream connections (like connections to a database or external API). Using gevent lets your application handle other requests at the same time it's waiting for those operations.

With gevent worker type we use the gevent.server.StreamServer to create a TCP server. That handles the transport layer, but we still need to parse the stream for HTTP requests, create the WSGI environment, call the WSGI application with the environment, and serialize an HTTP response.

The Gunicorn parser code is in message.py.

With the gevent_pywsgi worker, the parsing logic from gevent can be found in pywsgi.py.

@JeremyLoy

This comment has been minimized.

Copy link

commented Mar 5, 2019

Thank you for the through explanations @tilgovi , its much appreciated!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.