> we make heavy use of asyncio because it’s more performant
more performant than....what exactly? If I need to load 1000 rows from a database and splash them on a webpage, will my response time go from the 300ms it takes without asyncio to something "more performant", like 50ms? Answer: no. async only gives you throughput, it has nothing to do with "faster" as far as the Python interpreter / GIL / anything like that. If you aren't actually spanning among dozens/hundreds/thousands of network connections, non-blocking IO isn't buying you much at all over using blocking IO with threads, and of course async / greenlets / threads are not a prerequisite for non-blocking IO in any case (only select() is).
it's nice that uvloop seems to be working on removing the terrible performance latency that out-of-the-box asyncio adds, so that's a reason that asyncio can really be viable as a means of gaining throughput without adding lots of latency you wouldn't get with gevent. But I can do without the enforced async boilerplate. Thanks javascript!
I'm glad you said this. There's an async cargo cult going on, where every service must be written in "performant" async code, without knowing the actual resource and load requirements of an application.
From the last benchmark I ran [1] async IO was insignificantly faster than thread-per-connection blocking IO in terms of latency, and marginally faster only after we hit a large number of clients.
Async IO doesn't necessarily make your code faster, it just makes it difficult to read.
well it can also make things faster.
well in your example it won't.
but consider you need to load 4 requests and do operations on each of them. if you schedule them in an async fashion you can begin operating on the first one that's ready and not the first one you defined. and this is also often the case. a website does not just do one request to the database. mostly it runs multiple ones and often they don't interfere. like getting 20 rows and the count as a whole, there is just no need to start the first and wait till you have 20 rows and then start the second. you should always start both and wait till you have both.
yes it does not magically make your fetching 100 rows faster or your pbkdf2()/bcrypt() function. you still need to wait for those.
Will my response time go from the 300ms it takes without asyncio to something "more performant", like 50ms
If you have to do 1000 queries it could, since could async will make it feasible to do them parallel. If it's a single query, maybe async would make it feasible to shard the database.
It buys you the stack size of each thread which only matters if you have a stupid amount of connections.
In this article[1] the author makes a comparison between the 2 models and 7000 concurrent users will chew up 450MB of stack space. Of course this is adjustable.
> more performant than....what exactly? If I need to load 1000 rows from a database and splash them on a webpage, will my response time go from the 300ms it takes without asyncio to something "more performant", like 50ms?
Potentially, it depends on if you can do other tasks for the same request that don't depend on the data. You might be able to render most of the page for instance. It's not purely about throughput.
Please tell me that 300ms was made up too and that it's not really taking that long.
If you have to make several requests to db backend to fulfil one response then potentially asyncio allows you to make them in parallel rather than in series. Reducing latency of your response.
> If I need to load 1000 rows from a database and splash them on a webpage, will my response time go from the 300ms it takes without asyncio to something "more performant", like 50ms? Answer: no
Well, actually, yes. Without async rendering, your webpage is not ready until your 1000 rows of list is placed in Python memory then rendered to HTML as a whole then returned to your browser after like 300ms of server cost.
With async rendering, your webpage's headers and such can be returned immediately, thus your first-byte-to-response time can be done under 50ms, and your page loads by enumerating the rest of 1000 rows and renders the page incrementally.
We've just recently started using Sanic[0] paired with Redis to great effect for a very high throughput web service. It also uses Python 3 asyncio/uvloop at its core. So far very happy with it.
I have never found a good example of a Python web server that provides some mechanism for statefulness. Is it just fundamentally not possible to have shared state among requests handled by the threads of a process? Sanic's examples seem to be the same as Flask's: self-contained function calls attached to endpoints.
I keep hitting a wall with Python when I want to do something like:
1. subscribe to a websocket connection and keep the last received message in state
2. expose an http endpoint to let a client GET that last message.
Any idea how Sanic compares with Falcon? I read somewhere recently that Falcon was quite fast. I tried out Hug, which is built on Falcon, but only for a small demo app, not done any benchmarking.
Concurrency and parallelism is such a huge landscape of difficult problems and complexity that I doubt any such introduction exists. I never found one, anyway.
When working with Python and Ruby I find 80ms responses acceptable. In very optimized situations (no framework) this can do down to 20ms.
Now I've used some Haskell, OCaml and Go and I have learned that they can typically respond in <5ms. And that having a framework in place barely increases the response times.
In both cases this includes querying the db several times (db queries usually take less then a millisecond, Redis shall be quite similar to the extend that it does not change outcome).
<5ms makes it possible to not worry about caching (and thus cache invalidation) for a much longer time.
I've come to the conclusion that --considering other languages-- speed is not to be found in Python and Ruby.
Apart from the speed story there's also resource consumption, and in that game it is only compiled languages that truly compete.
Last point: give the point I make above and that nowadays "the web is the UI", I believe that languages for hi-perf application development should: compile to native and compile to JS. Candidates: OCaml/Reason (BuckleScript), Haskell (GHCJS), PureScript (ps-native), [please add if I forgot any]
> You get the benefits of a database, with the performance of RAM!
One of the benefits of modern RDBMS is that they make extremely sophisticated use of RAM, and all levels of fast to slow storage below that SSD / RAIDs / slow single spindle.
It is a relative thin layer of rust code between the Redis module interface and SQLite.
At the moment you can simply execute statements but any suggestion and feature request is very welcome.
Yes, it is possible to do join, to use the LIKE operator and pretty much everything that SQLite gives you.
It is a multi-thread module, which means that it does NOT block the main redis thread and perform quite well.
On my machine I achieved 50.000 inserts per seconds for the in memory database.
If you have any question feel free to ask here or to open issues and pull request in the main repo.
This is pretty neat. I've been using a plain Redis wrapper (aioredis) with uvloop and Sanic (https://github.com/rcarmo/newsfeed-corpus), but I'm going to have a peek at subconscious.
>One of the common complaints people have about python and other popular interpreted languages (Ruby, JavaScript, PHP, Perl, etc) is that they’re slow.
Proceeds to show an animation of posting a blog post that performs no faster than if it was built using Django.
Might be that the server is insanely slow, but I would have no problems reaching 10k page views per second with some basic PHP and even MariaDB on a low end E3-1230 server. Pretty sure more would be quite easy to...
It seems strange that they would claim that Python's libuv based event loop is twice as fast as Node.js's libuv based event loop. There's some context missing to that statement or it's flat out false.
[+] [-] zzzeek|8 years ago|reply
more performant than....what exactly? If I need to load 1000 rows from a database and splash them on a webpage, will my response time go from the 300ms it takes without asyncio to something "more performant", like 50ms? Answer: no. async only gives you throughput, it has nothing to do with "faster" as far as the Python interpreter / GIL / anything like that. If you aren't actually spanning among dozens/hundreds/thousands of network connections, non-blocking IO isn't buying you much at all over using blocking IO with threads, and of course async / greenlets / threads are not a prerequisite for non-blocking IO in any case (only select() is).
it's nice that uvloop seems to be working on removing the terrible performance latency that out-of-the-box asyncio adds, so that's a reason that asyncio can really be viable as a means of gaining throughput without adding lots of latency you wouldn't get with gevent. But I can do without the enforced async boilerplate. Thanks javascript!
[+] [-] bysin|8 years ago|reply
From the last benchmark I ran [1] async IO was insignificantly faster than thread-per-connection blocking IO in terms of latency, and marginally faster only after we hit a large number of clients.
Async IO doesn't necessarily make your code faster, it just makes it difficult to read.
[1] http://byteworm.com/evidence-based-research/2017/03/04/compa...
[+] [-] tyingq|8 years ago|reply
Then you'll really be irritated.
[+] [-] merb|8 years ago|reply
yes it does not magically make your fetching 100 rows faster or your pbkdf2()/bcrypt() function. you still need to wait for those.
[+] [-] ma2rten|8 years ago|reply
If you have to do 1000 queries it could, since could async will make it feasible to do them parallel. If it's a single query, maybe async would make it feasible to shard the database.
[+] [-] matthewaveryusa|8 years ago|reply
[1] http://byteworm.com/evidence-based-research/2017/03/04/compa...
[+] [-] flukus|8 years ago|reply
Potentially, it depends on if you can do other tasks for the same request that don't depend on the data. You might be able to render most of the page for instance. It's not purely about throughput.
Please tell me that 300ms was made up too and that it's not really taking that long.
[+] [-] RubyPinch|8 years ago|reply
it seems the main bottleneck when using aiohttp is aiohttp itself, which practically makes the use of uvloop irrelevant
[+] [-] anentropic|8 years ago|reply
[+] [-] est|8 years ago|reply
Well, actually, yes. Without async rendering, your webpage is not ready until your 1000 rows of list is placed in Python memory then rendered to HTML as a whole then returned to your browser after like 300ms of server cost.
With async rendering, your webpage's headers and such can be returned immediately, thus your first-byte-to-response time can be done under 50ms, and your page loads by enumerating the rest of 1000 rows and renders the page incrementally.
[+] [-] Dowwie|8 years ago|reply
[+] [-] erikcw|8 years ago|reply
[0] https://github.com/channelcat/sanic
[+] [-] sandGorgon|8 years ago|reply
It's built by Tom Christie - the original author of Django Rest Foundation.
http://discuss.apistar.org/t/how-does-api-star-fit-in-with-d...
[+] [-] Waterluvian|8 years ago|reply
I keep hitting a wall with Python when I want to do something like:
1. subscribe to a websocket connection and keep the last received message in state 2. expose an http endpoint to let a client GET that last message.
[+] [-] vram22|8 years ago|reply
[+] [-] fafhrd91|8 years ago|reply
[+] [-] wiremine|8 years ago|reply
[+] [-] mixmastamyk|8 years ago|reply
While I can write this kind of code, I don't feel like I completely understand some of the concepts.
[+] [-] mrks_|8 years ago|reply
https://pragprog.com/book/pb7con/seven-concurrency-models-in...
[+] [-] dom0|8 years ago|reply
[+] [-] michaelmcmillan|8 years ago|reply
[+] [-] cies|8 years ago|reply
When working with Python and Ruby I find 80ms responses acceptable. In very optimized situations (no framework) this can do down to 20ms.
Now I've used some Haskell, OCaml and Go and I have learned that they can typically respond in <5ms. And that having a framework in place barely increases the response times.
In both cases this includes querying the db several times (db queries usually take less then a millisecond, Redis shall be quite similar to the extend that it does not change outcome).
<5ms makes it possible to not worry about caching (and thus cache invalidation) for a much longer time.
I've come to the conclusion that --considering other languages-- speed is not to be found in Python and Ruby.
Apart from the speed story there's also resource consumption, and in that game it is only compiled languages that truly compete.
Last point: give the point I make above and that nowadays "the web is the UI", I believe that languages for hi-perf application development should: compile to native and compile to JS. Candidates: OCaml/Reason (BuckleScript), Haskell (GHCJS), PureScript (ps-native), [please add if I forgot any]
[+] [-] jitl|8 years ago|reply
I'm confused by the relationship between Paxos, the company, and Paxos, the algorithm. Do the authors of Paxos work for Paxos?
Edit:
https://en.m.wikipedia.org/wiki/Paxos_(computer_science)
Ah; both are named for a fictional financial systen
[+] [-] ipsum2|8 years ago|reply
[+] [-] mixmastamyk|8 years ago|reply
https://magic.io/blog/uvloop-blazing-fast-python-networking/
[+] [-] StreamBright|8 years ago|reply
I would prefer standard benchmarks for this. I hope they submit their framework to TechEnpower benchmarks.
https://www.techempower.com/benchmarks/
[+] [-] pekk|8 years ago|reply
[+] [-] njharman|8 years ago|reply
One of the benefits of modern RDBMS is that they make extremely sophisticated use of RAM, and all levels of fast to slow storage below that SSD / RAIDs / slow single spindle.
[+] [-] siscia|8 years ago|reply
It is a relative thin layer of rust code between the Redis module interface and SQLite.
At the moment you can simply execute statements but any suggestion and feature request is very welcome.
Yes, it is possible to do join, to use the LIKE operator and pretty much everything that SQLite gives you.
It is a multi-thread module, which means that it does NOT block the main redis thread and perform quite well. On my machine I achieved 50.000 inserts per seconds for the in memory database.
If you have any question feel free to ask here or to open issues and pull request in the main repo.
:)
[+] [-] rcarmo|8 years ago|reply
[+] [-] VT_Drew|8 years ago|reply
Proceeds to show an animation of posting a blog post that performs no faster than if it was built using Django.
[+] [-] NightlyDev|8 years ago|reply
Might be that the server is insanely slow, but I would have no problems reaching 10k page views per second with some basic PHP and even MariaDB on a low end E3-1230 server. Pretty sure more would be quite easy to...
[+] [-] fritzy|8 years ago|reply
[+] [-] GroSacASacs|8 years ago|reply
[+] [-] hasenj|8 years ago|reply
[+] [-] theprop|8 years ago|reply