Uwsgi with gevent vs threads

First of all, sorry for my poor English. In my project, I have many network I / O requests. The main data is stored in other projects, and access is provided through the web API (JSON / XML) survey. We use these APIs for each new user session (to obtain user information). And sometimes we have a problem with waiting for an answer. We use nginx + uwsgi + django. As you know, Django is synchronous (or blocking). We use uwsgi with a multi-threaded solution to solve the IO network wait problem. I decided to read about gevent. I understand the difference between collaborative and proactive multitasking. And I was hoping that gevent is the best solution, and then uwsgi themes for this problem (bottleneck in the I / O network). But the results were almost the same. Sometimes gevent was weaker. Maybe somewhere I'm wrong. Tell me please.

Here are uwsgi configuration examples. GEvent:

$ uwsgi --http :8001 --module ugtest.wsgi --gevent 40 --gevent-monkey-patch 

Threading:

 $ uwsgi --http :8001 --module ugtest.wsgi --enable-threads --threads 40 

Controller example:

 def simple_test_action(request): # get data from API without parsing (only for simple I/O test) data = _get_data_by_url(API_URL) return JsonResponse(data, safe=False) import httplib from urlparse import urlparse def _get_data_by_url(url): u = urlparse(url) if str(u.scheme).strip().lower() == 'https': conn = httplib.HTTPSConnection(u.netloc) else: conn = httplib.HTTPConnection(u.netloc) path_with_params = '%s?%s' % (u.path, u.query, ) conn.request("GET", path_with_params) resp = conn.getresponse() print resp.status, resp.reason body = resp.read() return body 

Test (with geventhttpclient ):

 def get_info(i): url = URL('http://localhost:8001/simpletestaction/') http = HTTPClient.from_url(url, concurrency=100, connection_timeout=60, network_timeout=60) try: response = http.get(url.request_uri) s = response.status_code body = response.read() finally: http.close() dt_start = dt.now() print 'Start: %s' % dt_start threads = [gevent.spawn(get_info, i) for i in xrange(401)] gevent.joinall(threads) dt_end = dt.now() print 'End: %s' % dt_end print dt_end-dt_start 

In both cases, I have the same time. What are the benefits of gevent / greenlets and collaborative multitasking in a similar problem (API proxy)?

+5
source share
2 answers

A concurrency 40 is not such that the gentent shines. Gevent near concurrency is not parallelism (or performance on demand), so having such a "low" level of concurrency is not a good way to get improvements.

As a rule, you will see gevent concurrency with the level of thousands, but not 40 :)

To block I / O streams, I / O is not bad (GIL is freed during I / O), gevent has the advantage of using resources (with 1000 python threads would be redundant) and eliminating the need to think of blocking and friends.

And, obviously, remember that your entire application must be gevent-friendly in order to gain an advantage, and django (by default) requires some configuration (as an example, database adapters must be modified using something friendly gevent).

+5
source

Non-blocking service is not about performance, but about concurrency. If 99% of the query time is spent on a subquery, you cannot just optimize these 99%. But when all available threads become busy, new clients are denied, although 99% of the threads' time is spent waiting for the completion of the subquery. A non-blocking service allows you to use this downtime by sharing it between β€œhandlers” that are not limited by the number of threads available. Thus, if 99% is expected, then another 1% is processed by the processor, so you can have 100 times more connections at the same time before maximizing your processor - without having 100% more threads, which can be too expensive (and with Python GIL you must use subprocesses that are even more expensive).

Now, as Roberto said, your code must be 100% non-blocking in order to be able to save downtime. However, as you can see from the percent example above, it becomes critical only when requests are almost completely tied to IO. If so, you probably don't need Django, at least for this part of your application.

+1
source

Source: https://habr.com/ru/post/1210863/


All Articles