Search code examples
performancepython-3.xtornadozeromqpyzmq

Which pyzmq implementation has the fastest throughput between @gen.coroutine, @asyncio.coroutine and async?


Currently in pzmq there are multiple ways to implement an asynchronous IO Loop all mentioned in the documentation. http://pyzmq.readthedocs.io/en/latest/api/index.html

From a pure performance point of view, it is not clear in the documentation if the choices are equivalent. These are:

  • Tornado @gen.coroutine
  • Native @asyncio.coroutine
  • Tornado async

So, which one has the best throughput in messages per second in a typical PUSH-PULL scenario as shown in the documentation examples? Why do we see a difference between them?


Solution

  • Results

    Contrary to my expectations, it seems both asyncio implementations in pyzmq are slower than the "legacy" tornado one.

    Tornado @gen.coroutine:

    Avg. Speed: 2160.26 msg/s
    

    Native @asyncio.coroutine:

    Avg. Speed: 1697.66 msg/s
    

    Tornado async:

    Avg. Speed: 1695.29 msg/s
    

    Also, the two asyncio implementations show bursts of up to 3536.27 msg/s every now and then, whereas the Tornado @gen.coroutine is very stable in throughput.

    Test Code

    For comparing I have used modified versions of:

    Tornado @gen.coroutine: https://github.com/zeromq/pyzmq/blob/master/examples/eventloop/coroutines.py

    Native @asyncio.coroutine: https://github.com/zeromq/pyzmq/blob/master/examples/asyncio/coroutines.py

    Tornado async: (Python 3.5+ only; included additional print coroutine) https://github.com/zeromq/pyzmq/blob/master/examples/asyncio/tornado_asyncio.py

    The modification consists of displaying the number of average messages per second every 5 seconds instead of the dots. In the PULL coroutine, I increment n = n + 1 and then in the printing coroutine I calculate v = n / (time.time() - start) and display it. Also there, I reset n = 0 and start = time.time() every 10,000 messages to prevent any offset effects in the measurement.

    Environment

    $ uname -a
    Linux localhost 4.6.3-300.fc24.x86_64 #1 SMP Fri Jun 24 20:52:41 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
    
    $ python3 --version
    Python 3.5.1
    
    >>> zmq.__version__
    '15.3.0'
    
    >>> tornado.version
    '4.3'