Commit d2aec125 authored by SVN-Git Migration's avatar SVN-Git Migration

Imported Upstream version 2.1.11

parent 4b082179
*.pyc
*.c
build
dist
conf
*.egg-info
*.so
*.pyd
*.dll
docs/source/api/generated
docs/gh-pages
setup.cfg
MANIFEST
Brian E. Granger <ellisonbg@gmail.com> Brian Granger <ellisonbg@gmail.com>
Daniel Lundin <dln@eintr.org> Daniel Lundin <dln@spotify.com>
Min Ragan-Kelley <benjaminrk@gmail.com> Min RK <benjaminrk@gmail.com>
Min Ragan-Kelley <benjaminrk@gmail.com> MinRK <benjaminrk@gmail.com>
Nicholas Piël <nicholas@nichol.as> nicholas <nicholas@bastet.ss.sitesupport.com>
include COPYING.LESSER
include README.rst
include setup.cfg.template
include setup.py
include setupegg.py
include zmqversion.py
include buildutils.py
graft docs
prune docs/build
prune docs/gh-pages
graft examples
graft zmq
graft perf
exclude setup.cfg
exclude zmq/libzmq*
# exclude docs/_static
# exclude docs/_templates
global-exclude *.so
global-exclude *.pyd
global-exclude *.pyc
global-exclude .git*
global-exclude .DS_Store
global-exclude .mailmap
Metadata-Version: 1.0
Name: pyzmq
Version: 2.1.10
Summary: Python bindings for 0MQ.
Home-page: http://github.com/zeromq/pyzmq
Author: Brian E. Granger, Min Ragan-Kelley
Author-email: zeromq-dev@lists.zeromq.org
License: LGPL
Download-URL: http://github.com/zeromq/pyzmq/downloads
Description:
PyZMQ is a lightweight and super-fast messaging library built on top of
the ZeroMQ library (http://www.zeromq.org).
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: Intended Audience :: Science/Research
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX
Classifier: Topic :: System :: Networking
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.5
Classifier: Programming Language :: Python :: 2.6
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.0
Classifier: Programming Language :: Python :: 3.1
Classifier: Programming Language :: Python :: 3.2
......@@ -8,7 +8,7 @@ This package contains Python bindings for `ØMQ <http://www.zeromq.org>`_.
Versioning
==========
Current release of pyzmq is 2.1.10, and targets libzmq-2.1.10. For libzmq
Current release of pyzmq is 2.1.11, and targets libzmq-2.1.11. For libzmq
2.0.x, use pyzmq release 2.0.10.1 or the 2.0.x development branch.
PyZMQ versioning follows libzmq versioning. In general, your pyzmq version should be the same
......@@ -16,17 +16,14 @@ as that of your libzmq, but due to the generally growing API of libzmq, your pyz
*not* be newer than your libzmq. This is a strict restriction for pyzmq <= 2.1.0, but we
intend to support libzmq >= 2.1.4 (the first 'stable' 2.1 release) for pyzmq 2.1.x.
ØMQ 3.0 and 4.0
---------------
For a summary of changes to pyzmq, see our `changelog <http://zeromq.github.com/pyzmq/changelog.html>`_.
As of 2.1.7, we have experimental support for the 3.0 API of libzmq,
developed at https://github.com/zeromq/zeromq3-0. No code to change, no flags to pass, just
build pyzmq against libzmq 3 and it should work. The pyzmq API has not changed, though
some syntax has been added to support new features, such as the LABEL routing prefix in 3.0.
2.1.9 adds support for the changes in the experimental 4.0 development branch at
https://github.com/zeromq/libzmq.
ØMQ 3.x
-------
As of 2.1.7, we have experimental support for the 3.x API of libzmq,
developed at https://github.com/zeromq/libzmq. No code to change, no flags to pass, just
build pyzmq against libzmq3 and it should work.
Documentation
=============
......@@ -82,7 +79,7 @@ A Python 2.6/win64 MSI for 2.1.7 was provided by Craig Austin (craig DOT austin
Our build scripts are much improved as of 2.1.4, so if you would like to contribute better
Windows installers, or have any improvements on existing releases, they would be much
appreciated. Simply ``python setup.py bdist_msi`` or ``python setupegg.py bdist_egg`` *should*
work, once you have a libzmq and Python. We simply don't have the VMs or time in which to cover
work, once you have libzmq and Python. We simply don't have the VMs or time in which to cover
all the bases ourselves.
.. note::
......@@ -98,7 +95,7 @@ After you have done this, follow these steps:
Tell pyzmq where libzmq is via the configure subcommand:
$ python setup.py configure --zmq=/path/to/zeromq2
$ python setup.py configure --zmq=/path/to/zeromq
or the zmq install directory on OSX/Linux:
......@@ -108,7 +105,7 @@ The argument should be a directory containing ``lib`` and ``include`` directorie
``libzmq`` and ``zmq.h`` respectively. For instance (on Windows), if you have downloaded pyzmq
and current libzmq into the same parent directory, this would be:
$ python setup.py configure --zmq=../zeromq-2.1.10
$ python setup.py configure --zmq=../zeromq-2.1.11
Second, run this command::
......
......@@ -248,7 +248,8 @@ def copy_and_patch_libzmq(ZMQ, libzmq):
fatal("Please specify zmq prefix via `setup.py configure --zmq=/path/to/zmq` "
"or copy libzmq into zmq/ manually prior to running bdist.")
try:
lib = pjoin(ZMQ, 'lib', libzmq)
# resolve real file through symlinks
lib = os.path.realpath(pjoin(ZMQ, 'lib', libzmq))
print ("copying %s -> %s"%(lib, local))
shutil.copy(lib, local)
except Exception:
......@@ -256,11 +257,6 @@ def copy_and_patch_libzmq(ZMQ, libzmq):
fatal("Could not copy libzmq into zmq/, which is necessary for bdist. "
"Please specify zmq prefix via `setup.py configure --zmq=/path/to/zmq` "
"or copy libzmq into zmq/ manually.")
finally:
# link libzmq.dylib -> libzmq.1.dylib
link = localpath('zmq',libzmq.replace('.1',''))
if not os.path.exists(link):
os.symlink(libzmq, link)
if sys.platform == 'darwin':
# patch install_name on darwin, instead of using rpath
......
......@@ -18,10 +18,9 @@ if __name__ == '__main__':
docwriter = ApiDocWriter(package,rst_extension='.rst')
# You have to escape the . here because . is a special char for regexps.
# You must do make clean if you change this!
docwriter.package_skip_patterns += [ r'\.tests$' ]
docwriter.package_skip_patterns += [ r'\.tests$', r'\.platform$' ]
docwriter.module_skip_patterns += [ r'\.tests',
r'win32_support']
docwriter.module_skip_patterns += [ r'\.tests' ]
# Now, generate the outputs
docwriter.write_api_docs(outdir)
......
@ECHO OFF
REM Command file for Sphinx documentation
set SPHINXBUILD=sphinx-build
set BUILDDIR=_build
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
)
if "%1" == "" goto help
if "%1" == "help" (
:help
echo.Please use `make ^<target^>` where ^<target^> is one of
echo. html to make standalone HTML files
echo. dirhtml to make HTML files named index.html in directories
echo. pickle to make pickle files
echo. json to make JSON files
echo. htmlhelp to make HTML files and a HTML help project
echo. qthelp to make HTML files and a qthelp project
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
echo. changes to make an overview over all changed/added/deprecated items
echo. linkcheck to check all external links for integrity
echo. doctest to run all doctests embedded in the documentation if enabled
goto end
)
if "%1" == "clean" (
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
del /q /s %BUILDDIR%\*
goto end
)
if "%1" == "html" (
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
goto end
)
if "%1" == "dirhtml" (
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
goto end
)
if "%1" == "pickle" (
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
echo.
echo.Build finished; now you can process the pickle files.
goto end
)
if "%1" == "json" (
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
echo.
echo.Build finished; now you can process the JSON files.
goto end
)
if "%1" == "htmlhelp" (
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
echo.
echo.Build finished; now you can run HTML Help Workshop with the ^
.hhp project file in %BUILDDIR%/htmlhelp.
goto end
)
if "%1" == "qthelp" (
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
echo.
echo.Build finished; now you can run "qcollectiongenerator" with the ^
.qhcp project file in %BUILDDIR%/qthelp, like this:
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\PyZMQ.qhcp
echo.To view the help file:
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\PyZMQ.ghc
goto end
)
if "%1" == "latex" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
echo.
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "changes" (
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
echo.
echo.The overview file is in %BUILDDIR%/changes.
goto end
)
if "%1" == "linkcheck" (
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
echo.
echo.Link check complete; look for any errors in the above output ^
or in %BUILDDIR%/linkcheck/output.txt.
goto end
)
if "%1" == "doctest" (
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
echo.
echo.Testing of doctests in the sources finished, look at the ^
results in %BUILDDIR%/doctest/output.txt.
goto end
)
:end
......@@ -9,11 +9,47 @@ Changes in PyZMQ
This is a coarse summary of changes in pyzmq versions. For a real changelog, consult the
`git log <https://github.com/zeromq/pyzmq/commits>`_
2.1.11
======
* remove support for LABEL prefixes. A major feature of libzmq-3.0, the LABEL
prefix, has been removed from libzmq, prior to the first stable libzmq 3.x release.
* The prefix argument to :meth:`~.Socket.send_multipart` remains, but it continue to behave in
exactly the same way as it always has on 2.1.x, simply prepending message parts.
* :meth:`~.Socket.recv_multipart` will always return a list, because prefixes are once
again indistinguishable from regular message parts.
* add :meth:`.Socket.poll` method, for simple polling of events on a single socket.
* no longer require monkeypatching tornado IOLoop. The :class:`.ioloop.ZMQPoller` class
is a poller implementation that matches tornado's expectations, and pyzmq sockets can
be used with any tornado application just by specifying the use of this poller. The
pyzmq IOLoop implementation now only trivially differs from tornado's.
It is still recommended to use :func:`.ioloop.install`, which sets *both* the zmq and
tornado global IOLoop instances to the same object, but it is no longer necessary.
.. warning::
The most important part of this change is that the ``IOLoop.READ/WRITE/ERROR``
constants now match tornado's, rather than being mapped directly to the zmq
``POLLIN/OUT/ERR``. So applications that used the low-level :meth:`IOLoop.add_handler`
code with ``POLLIN/OUT/ERR`` directly (used to work, but was incorrect), rather than
using the IOLoop class constants will no longer work. Fixing these to use the IOLoop
constants should be insensitive to the actual value of the constants.
2.1.10
======
* Add support for libzmq-3.0 LABEL prefixes:
.. warning::
This feature has been removed from libzmq, and thus removed from future pyzmq
as well.
* send a message with label-prefix with:
.. sourcecode:: python
......
......@@ -13,14 +13,51 @@ but instead of calling :meth:`~.Socket.recv` directly, you register a callback w
:meth:`~.ZMQStream.on_recv`. callbacks can also be registered for send and error events
with :meth:`~.ZMQStream.on_send` and :meth:`~.ZMQStream.on_err` respectively.
.. Note::
We have not explored using ØMQ in a full Tornado environment, and we do not include
any parts of Tornado outside of IOLoop and the couple of helper classes used in
IOLoop.
:func:`install()`
-----------------
``send``
--------
With PyZMQ's ioloop, you can use zmq sockets in any tornado application. You must first
install PyZMQ's :class:`.IOLoop`, with the :func:`.ioloop.install` function:
.. sourcecode:: python
from zmq.eventloop import ioloop
ioloop.install()
This sets the global instance of :class:`tornado.ioloop.IOLoop` with the global instance of
our IOLoop class. The reason this must happen is that tornado objects avoid having to pass
the active IOLoop instance around by having a staticmethod :meth:`.IOLoop.instance`, which
always returns the active instance. If PyZMQ's IOLoop is installed after the first call to
:meth:`.IOLoop.instance()` (called in almost every tornado object constructor), then it will
raise an :exc:`AssertionError`, because the global IOLoop instance has already been
created, and proceeding would result in not all objects being associated with the right
IOLoop.
It is possible to use PyZMQ sockets with tornado *without* calling :func:`.ioloop.install`,
but it is less convenient. First, you must instruct the tornado IOLoop to use the zmq poller:
.. sourcecode:: python
from tornado.ioloop import IOLoop
from zmq.eventloop.ioloop import ZMQPoller
loop = IOLoop(ZMQPoller())
Then, when you instantiate tornado and ZMQStream objects, you must pass the `io_loop`
argument to ensure that they use this loop, instead of the global instance. You can
install this IOLoop as the global tornado instance, with:
.. sourcecode:: python
loop.install()
but it will **NOT** be the global *pyzmq* IOLoop instance, so it must still be passed to
your ZMQStream constructors.
:meth:`send`
------------
ZMQStream objects do have :meth:`~.ZMQStream.send` and :meth:`~.ZMQStream.send_multipart`
methods, which behaves the same way as :meth:`.Socket.send`, but instead of sending right
......@@ -29,12 +66,14 @@ is met, or a ``REQ/REP`` pattern prohibits sending at a certain point). Messages
send will also be passed to the callback registered with :meth:`~.ZMQStream.on_send` after
sending.
``on_recv``
-----------
:meth:`on_recv`
---------------
:meth:`.ZMQStream.on_recv` is the primary method for using a ZMQStream. It registers a
callback to fire with messages as they are received, which will *always* be multipart,
even if its length is 1. You can easily use this to build things like an echo socket::
even if its length is 1. You can easily use this to build things like an echo socket:
.. sourcecode:: python
s = ctx.socket(zmq.REP)
s.bind('tcp://localhost:12345')
......@@ -46,10 +85,11 @@ even if its length is 1. You can easily use this to build things like an echo so
loop.start()
on_recv can also take a `copy` flag, just like :meth:`.Socket.recv`. If `copy=False`, then
callbacks registered with on_recv will receive tracked Message objects instead of bytes.
callbacks registered with on_recv will receive tracked :class:`.Message` objects instead of
bytes.
``flush``
---------
:meth:`flush`
-------------
Sometimes with an eventloop, there can be multiple events ready on a single iteration of
the loop. The :meth:`~.ZMQStream.flush` method allows developers to pull messages off of
......
......@@ -10,28 +10,33 @@ PyZMQ Documentation
:Release: |release|
:Date: |today|
.. Note::
PyZMQ versioning follows zeromq, so your pyzmq version should match that of your
zeromq. Building the same pyzmq against various versions of zeromq should only result
in the addition/removal of a few socket types and socket options, depending on
the active zeromq's support.
PyZMQ is the Python bindings for ØMQ_, written almost entirely in Cython_. This
documentation currently contains notes on some important aspects of developing PyZMQ and
an overview of what the ØMQ API looks like in Python. For information on how to use
ØMQ in general, see the excellent `ØMQ Manual`_.
ØMQ in general, see the excellent `ØMQ Guide`_, which has examples translated into many
languages, including Python.
.. Note::
Please don't hesitate to report pyzmq issues to our tracker_ on GitHub, or send
questions to the ØMQ `mailing list`_ or `IRC Channel`_.
As of PyZMQ 2.1.7, PyZMQ has experimental support for the libzmq-3.0 development version,
and has dropped support for the zeromq-2.0 series.
:ref:`Summary of Changes in PyZMQ <changelog>`
Please don't hesitate to report pyzmq issues to our tracker_ on GitHub.
:ref:`Summary of Changes in PyZMQ <changelog>`
PyZMQ Versioning
================
PyZMQ versioning follows libzmq, so your pyzmq version should match that of your
libzmq. Building the same pyzmq against various versions of libzmq is supported,
and should only result in the addition/removal of a few socket types and socket
options, depending on the active libzmq's support.
Binary distributions (eggs or MSIs on `PyPI <http://pypi.python.org/pypi/pyzmq>`__
or `GitHub <https://www.github.com/zeromq/pyzmq/downloads>`__) of PyZMQ ship with
matching libzmq release built with default configuration.
PyZMQ aims to support all stable ( ≥2.1.4 ) and active development ( ≥3.1.0 )
versions of libzmq.
Notes from developing PyZMQ
......@@ -69,11 +74,15 @@ Links
=====
* ØMQ_ Home
* The `ØMQ Guide`_
* `PyZMQ Installation`_ notes on the ZeroMQ website
* PyZMQ on GitHub_
* Issue Tracker_
.. _ØMQ: http://www.zeromq.org
.. _ØMQ Guide: http://zguide.zeromq.org
.. _mailing list: http://www.zeromq.org/docs:mailing-lists
.. _IRC Channel: http://www.zeromq.org/chatroom
.. _Cython: http://cython.org/
.. _GitHub: https://www.github.com/zeromq/pyzmq
.. _ØMQ Manual: http://www.zeromq.org/intro:read-the-manual
......
......@@ -13,7 +13,12 @@ tunneling ØMQ connections over ssh in simple cases. These functions have been b
pyzmq as :mod:`zmq.ssh` under IPython's BSD license.
PyZMQ will use the shell ssh command via pexpect_ by default, but it also supports
using paramiko_ for tunnels, so it should also work on Windows.
using paramiko_ for tunnels, so it should work on Windows.
.. note::
pexpect has no Python3 support at this time, so Python 3 users should get Thomas
Kluyver's `pexpect-u`_ fork.
An SSH tunnel has five basic components:
......@@ -70,5 +75,6 @@ rather than the remote one that wouldn't actually work.
.. _IPython: http://ipython.org
.. _pexpect: http://www.noah.org/wiki/pexpect
.. _pexpect-u: http://pypi.python.org/pypi/pexpect-u
.. _paramiko: http://www.lag.net/paramiko/
"""Async web request example with tornado.
Requests to localhost:8888 will be relayed via 0MQ to a slow responder,
who will take 1-5 seconds to respond. The tornado app will remain responsive
duriung this time, and when the worker replies, the web request will finish.
A '.' is printed every 100ms to demonstrate that the zmq request is not blocking
the event loop.
"""
import sys
import random
import threading
import time
import zmq
from zmq.eventloop import ioloop, zmqstream
"""
ioloop.install() must be called prior to instantiating *any* tornado objects,
and ideally before importing anything from tornado, just to be safe.
install() sets the singleton instance of tornado.ioloop.IOLoop with zmq's
IOLoop. If this is not done properly, multiple IOLoop instances may be
created, which will have the effect of some subset of handlers never being
called, because only one loop will be running.
"""
ioloop.install()
import tornado
from tornado import web
def slow_responder():
"""thread for slowly responding to replies."""
ctx = zmq.Context.instance()
socket = ctx.socket(zmq.REP)
socket.linger = 0
socket.bind('tcp://127.0.0.1:5555')
i=0
while True:
msg = socket.recv()
print "\nworker received %r\n" % msg
time.sleep(random.randint(1,5))
socket.send(msg + " to you too, #%i" % i)
i+=1
def dot():
"""callback for showing that IOLoop is still responsive while we wait"""
sys.stdout.write('.')
sys.stdout.flush()
def printer(msg):
print (msg)
class TestHandler(web.RequestHandler):
@web.asynchronous
def get(self):
ctx = zmq.Context.instance()
s = ctx.socket(zmq.REQ)
s.connect('tcp://127.0.0.1:5555')
# send request to worker
s.send('hello')
loop = ioloop.IOLoop.instance()
self.stream = zmqstream.ZMQStream(s)
self.stream.on_recv(self.handle_reply)
def handle_reply(self, msg):
# finish web request with worker's reply
reply = msg[0]
print "\nfinishing with %r\n" % reply,
self.stream.close()
self.write(reply)
self.finish()
def main():
worker = threading.Thread(target=slow_responder)
worker.daemon=True
worker.start()
application = web.Application([(r"/", TestHandler)])
beat = ioloop.PeriodicCallback(dot, 100)
beat.start()
application.listen(8888)
try:
ioloop.IOLoop.instance().start()
except KeyboardInterrupt:
print ' Interrupted'
if __name__ == "__main__":
main()
import zmq
from zmq.eventloop import ioloop, zmqstream
import tornado
import tornado.web
"""
kind of hacky way to replace tornado ioloop with zmqs..
this doesn't ALWAYS work depending on what
parts of tornado you are using
ioloop.install() must be called prior to instantiating *any* tornado objects,
and ideally before importing anything from tornado, just to be safe.
install() sets the singleton instance of tornado.ioloop.IOLoop with zmq's
IOLoop. If this is not done properly, multiple IOLoop instances may be
created, which will have the effect of some subset of handlers never being
called, because only one loop will be running.
"""
tornado.ioloop = ioloop
ioloop.install()
import tornado
import tornado.web
"""
......@@ -24,7 +29,7 @@ def printer(msg):
ctx = zmq.Context()
s = ctx.socket(zmq.REQ)
s.connect('tcp://127.0.0.1:5555')
stream = zmqstream.ZMQStream(s, tornado.ioloop.IOLoop.instance())
stream = zmqstream.ZMQStream(s)
stream.on_recv(printer)
class TestHandler(tornado.web.RequestHandler):
......@@ -36,7 +41,7 @@ application = tornado.web.Application([(r"/", TestHandler)])
if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
ioloop.IOLoop.instance().start()
import re,time
import sys
from subprocess import Popen,PIPE
from local_lat import main as local_lat
from local_thr import main as local_thr
from remote_lat import main as remote_lat
from remote_thr import main as remote_thr
def run_thr(args):
local = Popen('python local_thr.py'.split()+args,stdout=PIPE,stdin=PIPE)
remote = Popen('python remote_thr.py'.split()+args,stdout=PIPE,stdin=PIPE)
remote.wait()
local.wait()
out,_ = local.communicate()
lines = out.splitlines()
result = lines[-1]
throughput = re.findall(r'[0-9\.]+',result)[0]
return float(throughput)
def run_lat(args):
local = Popen('python local_lat.py'.split()+args,stdout=PIPE,stdin=PIPE)
remote = Popen('python remote_lat.py'.split()+args,stdout=PIPE,stdin=PIPE)
line = ''
while 'latency' not in line:
line = remote.stdout.readline()
if 'latency' in line:
latency = re.findall(r'[0-9\.]+',line)[0]
remote.wait()
local.wait()
return float(latency)
def multi_lat(args, n=3):
lats = [ run_lat(args) for i in xrange(3) ]
avg = sum(lats) / len(lats)
return avg,min(lats),max(lats)
def multi_thr(args, n=3):
thrs = [ run_thr(args) for i in xrange(3) ]
avg = sum(thrs) / len(thrs)
return avg,min(thrs),max(thrs)
def generate_vs_msg_size(nmsgs, msg_sizes=[2**p for p in range(6,21)], samples=5):
print nmsgs
x = msg_sizes
thr = []
lat = []
for msg_size in msg_sizes:
args = ('tcp://127.0.0.1:12345 %i %i'%(msg_size, nmsgs)).split()
thr.append(multi_thr(args,samples))
print 'thr: %i %s'%(msg_size, thr[-1])
lat.append(multi_lat(args,samples))
print 'lat: %i %s'%(msg_size, lat[-1])
return x,thr,lat
def generate_vs_nmsgs(msg_size, nmsgs_s=[2**p for p in range(4,14)], samples=5):
print msg_size
x = nmsgs_s
thr = []
lat = []
for nmsgs in nmsgs_s:
args = ('tcp://127.0.0.1:12345 %i %i'%(msg_size, nmsgs)).split()
thr.append(multi_thr(args,samples))
print 'thr: %i %s'%(nmsgs, thr[-1])
lat.append(multi_lat(args,samples))
print 'lat: %i %s'%(nmsgs, lat[-1])
return x,thr,lat
def do_plot(x,thr,lat, ref=1024, vs='nmsgs'):
import pylab
pylab.figure()
if vs == 'msg_size':
title = "%i msgs"%ref
xlabel = "msg size (B)"
else:
title = "msg size = %i B"%ref
xlabel = "nmsgs"
pylab.grid(True, which='major')
# pylab.grid(True, which='minor')
pylab.title(title)
pylab.xlabel(xlabel)
t_a,t_min,t_max = zip(*thr)
pylab.loglog(x,t_a,'b',label='throughput')
pylab.loglog(x,t_min,'b:')
pylab.loglog(x,t_max,'b:')
pylab.ylabel("Mb/s")
pylab.legend(loc='upper left')
ax2 = pylab.twinx()
l_a,l_min,l_max = zip(*lat)
pylab.loglog(x,l_a,'g',label='latency')
pylab.loglog(x,l_min,'g:')