Live data from Hacker News

Making 1M requests with Python-aiohttp

pawelmhm.github.io

61–70 of 84 posts

Re: Making 1M requests with Python-aiohttp

#61
post #8

Earlier quoted context omitted.

I guess I don't know how JS was any more "designed for" async than python was.

From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Even... : JavaScript has a concurrency model based on an "event loop". This model is quite different than the model in other languages like C or Java. ... A very interesting property of the event loop model is that JavaScript, unlike a lot of other languages, never blocks. Handling I/O is typically performed via events and callbacks, so when the application…

>A very interesting property of the event loop model is that JavaScript, unlike a lot of other languages, never blocks.

JavaScript actually always blocks. It's only external function calls that somebody took care to write in an evented style that don't block -- but anything written in pure Javascript (from for loops to text manipulation) blocks.

JS single-thread async without preemptiveness is not something to write home about...

Re: Making 1M requests with Python-aiohttp

#62
post #15
post #8

Earlier quoted context omitted.

From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Even... : JavaScript has a concurrency model based on an "event loop". This model is quite different than the model in other languages like C or Java. ... A very interesting property of the event loop model is that JavaScript, unlike a lot of other languages, never blocks. Handling I/O is typically performed via events and callbacks, so when the application…

>>JavaScript, unlike a lot of other languages, never blocks I think that's a little strong. It's more like "The group controlling Javascript has mostly tried to discourage introduction of things that block". You can, for example, do a blocking XMLHttpRequest. It's deprecated, but possible. https://jsfiddle.net/923d5sda/

You can do blocking everything.

A 10.000 repetitions for look while block the whole interpreter for its duration.

Any JSON parsing does the same.

Processing strings.

Doing math work.

...

Re: Making 1M requests with Python-aiohttp

#63
post #10

1,000,000 requests in 52 minutes is just 320 req/sec. Am I missing something? What's so amazing about this? I just deployed some production feed that serves at 1955 requests/second on a cheap VPS in freaking PHP, one of the slowest languages out there.

Why you say is not amazing? Honestly curious here :)

Because it's like Dr Evil asking the UN leaders for "ONE MILLION DOLLARS" to not destroy the world...

https://www.youtube.com/watch?v=cKKHSAE1gIs

Re: Making 1M requests with Python-aiohttp

#64

Earlier quoted context omitted.

Is there anything inherent to Python3 that is slower than Python2? Or is it just some of the performant packages still have not been ported to Python3?

i keep looking for a reason to switch to python 3 and cant find one. Plus if I want to use the cool stuff in Pypy.. then I better not ! overall - very less reason to consider Py3 at all. Performance would have been one - if there were a comparison between gevent and asyncio.

A few reasons which made me switch:

  - Python 2 will be EOL in 2020, that's four years

  - vastly improved Unicode support

  - a number new libraries are Python 3 only

  - asyncio and the new async syntax

  - exception chaining (!)

  - type annotations

  - lots of improvements all over the place

Re: Making 1M requests with Python-aiohttp

#65

Earlier quoted context omitted.

but Python 3 is not really an upgrade is it ? it is a very different language and most people who are pushing (downvoting?) for Python 3 dont seem to understand that. I have zero problems with Python 3 per se - but when the vast majority of the ecosystem is on Py2 and there is no difference in performance... then I see no reason to consider any breakages.

I think over time watching this behavior like the downvotes you received, I've figured it out. The idea is that newer folks come into Python, many don't want to learn the dominant version in effort to focus on the future as they understand it. So 2 continuing to live is viewed as a threat to that investment. Even though the two aren't that different and shouldn't matter which one you use, that isn't a popular point t…

Nah. I'm a long-time Python developer (10 years+) and I moved everything over to Python 3 because there are so many advantages. This includes a number of massive internal code bases that I maintain at my day job. Porting is surprisingly easy nowadays, it used to hurt a lot more.

Management is fine with development time spent on migrating to Python 3, since it's an investment in the future (Python 2 will be EOL in 2020!).

Re: Making 1M requests with Python-aiohttp

#66
post #41

Earlier quoted context omitted.

I see you've been downvoted. Interesting, you said that you haven't found a reason to switch and someone looked at it and thought "How dare you not find a reason to switch, here let's teach you a lesson". But in large I agree. 3 hasn't provided enought of a carrot and 2 hasn't been enough of a pain for many people to want to switch. Especially when it comes to existing stable code bases. For new development, yes, man…

but Python 3 is not really an upgrade is it ? it is a very different language and most people who are pushing (downvoting?) for Python 3 dont seem to understand that. I have zero problems with Python 3 per se - but when the vast majority of the ecosystem is on Py2 and there is no difference in performance... then I see no reason to consider any breakages.

It is NOT a different language. It's not backwards compatible, sure, but usually, only minor changes are required and 2to3 helps a lot. At this point, pretty much all of the libraries are ported and their API stays the same. The libraries which haven't been ported yet are either notable exceptions (Twisted!) or are unmaintained.

Very helpful for porting: http://python-future.org

Re: Making 1M requests with Python-aiohttp

#67
post #11

First off, awesome to see more benchmarks (even if it's just personal experimentation) for synchronous vs asyncio performance. I think the real argument for asyncio right now is that it makes it very easy for you to write extremely efficient code, even for hobbyist projects. Even though your experiment is only handling 320 req/s, that you were able to do that so quickly and with very, very little optimization is, I t…

Thanks for feedback.

> You would probably handle more requests if you changed that -- I would do the file access in a run_in_executor with a max executor workers of 1000.

This is really good point. I'm going to check this and edit post adding this information there.

> Also, the placement of your semaphore acquisition doesn't make any sense to me. I would create a dedicated coroutine like this:

looking into my semaphore code next day after writing it I do wonder if I'm using it correctly. I assumed it works correctly because it fixed my "too many open files" exception, so it seems to mean that I'm no longer exceeding 1024 open files limits. Can you clarify why you think my use of semaphore does not make sense and why your suggestion is better? What is the benefit of dedicated coroutine?

> That being said, it also doesn't make any sense to me to have the semaphore in the client code, since the error is in the server code.

I admit that I focused more on my client than server. One thing that worries me about my test server is that it does not print any exceptions. Either it does not fail at all, which seems unlikely, or it fails silently, which is more likely and is bad. So I need to check my server code to see what exactly happens there.

> it also doesn't make any sense to me to have the semaphore in the client code, since the error is in the server code.

main reason for semaphore in client code is that it should stop client from making over 1k connections at a time. My logic here is that if client wont make 1k connections at a time - server wont receive 1k connections at a time and thus there will be no problem of too many open files on server (it won't have to send more than 1k responses). However I see that this logic may not be totally correct, other comment points out that it's possible for sockets to "hang around" after closing: https://news.ycombinator.com/item?id=11557672 so I need to review that and edit post.

> https://docs.python.org/3/library/asyncio-dev.html#debug-mod...

this looks really great, will look into this thanks.

Re: Making 1M requests with Python-aiohttp

#68
post #64

Earlier quoted context omitted.

i keep looking for a reason to switch to python 3 and cant find one. Plus if I want to use the cool stuff in Pypy.. then I better not ! overall - very less reason to consider Py3 at all. Performance would have been one - if there were a comparison between gevent and asyncio.

A few reasons which made me switch: - Python 2 will be EOL in 2020, that's four years - vastly improved Unicode support - a number new libraries are Python 3 only - asyncio and the new async syntax - exception chaining (!) - type annotations - lots of improvements all over the place

Python 2 will not be EOL in 4 years. Not with the billions of lines of code out there. If the Python foundation dares to do this, it will create a fork. Probably even funded by Dropbox, Google and the like.

I wont dispute you on any other aspects - except two. have you tried using gevent versus asyncio ? gevent is running in production at several of the largest API services in the world. Asyncio is not yet deployed at this scale.

Second about new libraries being python 3 only - really dispute that. In fact its the other way around. For example, the brand new Tensorflow library (which google uses in production for its own AI) was released on Python 2 only .. and Python 3 support was later patched in. This is the case with every new library of consequence that I'm seeing.

Re: Making 1M requests with Python-aiohttp

#69

Earlier quoted context omitted.

This is a genuine question: in what ways is Python's async implementation lacking? Could it have been baked in a better way? In what ways do languages that were supposedly designed for async programming different than Python? Python is definitely lacking an elegant interface for async programming.

simple reason - there is NO framework that is built ground up for nodejs style async programming. Obviously there is Twisted and Tornado - but gevent or asyncio are actually the paradigms that people are using now. If there were a Flask like framework that was ground up built to leverage async (rather than bolting it on) and included all the batteries for web development.. then python would have a serious edge over n…

Tornado works in pretty much the same way as asyncio.

Re: Making 1M requests with Python-aiohttp

#70
post #54
post #49

Re the EADDRNOTAVAIL from socket.connect(), If you're connecting to 127.0.0.1:8080, then each connection from 127.0.0.1 is going to be assigned an ephemeral TCP source port. There are only a finite number of such ports available, on the order of ~30-50k, which limits the number of connections from a single address to a specific endpoint. If you're doing 100k TCP connections with 1k concurrent conections, it's feasibl…

Generally its the upper 32k ports that are ephemeral, and if your churn more than that per minute in connections, you'll run into that TIME_WAIT issue. Hacky way to get around that is to enable tcp_tw_reuse which will let you reuse ports, but it can be risky if you get a SYN from the previous connection that happens to lineup with segment number of the current connection (which will close your connection). Shouldn't…

For benchmarking loopback connections, addressing really shouldn't be an issue, as you have an entire /8-subnet to split between your client(s) and server(s) (127.0.0.0/8). You would need some logic to set up eg 10.000 listening servers, and 1000.000 clients to get it working, and at some point you'd probably run into memory or other limits.

I'm a little surprised some simple googling didn't turn up any examples of this - I'm sure someone have tried it out in order to do some benchmarking of high-performance network servers/services?

Apparently ipv6 changes this to a single (loopback) address, but then again, with ipv6 you can use entire subnets per network card.

Post reply on HN