-
Notifications
You must be signed in to change notification settings - Fork 631
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
zero-copy support in cffi backend #1365
Conversation
This is great! Supporting the buffer interface isn't enough for the cffi backend to support zero-copy sends, though, which is what the In the pypy2 tests, it looks like B = numpy.frombuffer(msg, A.dtype).reshape(A.shape)
TypeError: expected string or Unicode object, Frame found maybe need a version check or direct check for the presence of this bufferable type? |
There was a bug in PyPy, the fix should appear in the pypy2 nightly build tomorrow. |
Is there something I can do to get this going? |
You could give it a go. To implement zero-copy, Frame needs to match the Cython version more, which you can use as reference. Mainly:
|
in a322aa0 I
Now test_multi_tracker in test_message.py hangs. How do I instrument the callbacks so I can see what is not being called? I don't see the |
setup.py
Outdated
|
||
# whether any kind of bdist is happening | ||
# do this before importing anything from distutils | ||
doing_bdist = any(arg.startswith('bdist') for arg in sys.argv[1:]) | ||
|
||
if any(bdist in sys.argv for bdist in ['sdist', 'bdist_wheel', 'bdist_egg']): | ||
import setuptools | ||
from setuptools import setup |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
any supported python should be able to use setuptools, and I think is to be preferred over distutils where possible
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we're switching to requiring setuptools, let's make sure to avoid the main reason we haven't required setuptools: that it breaks python setup.py install
by implicitly doing egg installs and corrupting sys.path:
from setuptools.command.bdist_egg import bdist_egg
class bdist_egg_disabled(bdist_egg):
"""Disabled version of bdist_egg
Prevents setup.py install from performing setuptools' default easy_install,
which it should never ever do.
"""
def run(self):
sys.exit(
"Aborting implicit building of eggs. Use `pip install .` to install from source."
)
...
setup_args['cmdclass'] = {
...
'bdist_egg': bdist_egg if 'bdist_egg' in sys.argv else bdist_egg_disabled,
}
buildutils/build_cffi.py
Outdated
library_dirs=cfg['library_dirs'], | ||
runtime_library_dirs=cfg['runtime_library_dirs'], | ||
source=""" | ||
#include <stdio.h> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this be in a .c
file instead of inlined?
setup.py
Outdated
|
||
# whether any kind of bdist is happening | ||
# do this before importing anything from distutils | ||
doing_bdist = any(arg.startswith('bdist') for arg in sys.argv[1:]) | ||
|
||
if any(bdist in sys.argv for bdist in ['sdist', 'bdist_wheel', 'bdist_egg']): | ||
import setuptools | ||
from setuptools import setup |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we're switching to requiring setuptools, let's make sure to avoid the main reason we haven't required setuptools: that it breaks python setup.py install
by implicitly doing egg installs and corrupting sys.path:
from setuptools.command.bdist_egg import bdist_egg
class bdist_egg_disabled(bdist_egg):
"""Disabled version of bdist_egg
Prevents setup.py install from performing setuptools' default easy_install,
which it should never ever do.
"""
def run(self):
sys.exit(
"Aborting implicit building of eggs. Use `pip install .` to install from source."
)
...
setup_args['cmdclass'] = {
...
'bdist_egg': bdist_egg if 'bdist_egg' in sys.argv else bdist_egg_disabled,
}
9b5cb5e
to
a758f8a
Compare
- it's long enough that it's easier to be a standalone file - load constant_names without zmq being importable - address formatting, dropped py2compat
it's called lib now
22fbd09
to
1f821b3
Compare
- use manual malloc/free as ffi.new has the wrong lifecycle - implement zero-copy recv - get buffer from zmq_msg
zero-copy now works in PyPy. Thanks @mattip! |
Thanks for finishing this up. Are there any benchmarks for pyzmq? |
I found https://github.com/achimnol/asyncio-zmq-benchmark (that @minrk contributed to). Is that still relevant? |
When trying out PyPy2 with spyder via the spyder-kernels package (which is extends the ipython protocol?), I discovered that CFFI-based
Frame
was not working correctly: it did not support the buffer protocol. PyPy extends the ability of pure python classes to support the buffer protocol. If you inherit from the__pypy__.bufferable.bufferable
class and then instaniate an instance of your classb
, callngmemoryview(b)
will callself.__buffer__(flags)
and give you a chance to return a buffer.I implemented this, but it seems there is some code in the cython backend to release the buffer via a gc callback? In any case, I unskipped some of the tests.
Does this look OK? The only tests that are failing are the ones that check
tracker.done
, which makes me think maybe this is leaking memory.