-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
Add PyPy support #67
Comments
"the main idea would be to use cffi instead of C API, not sure if it's feasible" http://cffi.readthedocs.org/en/release-0.5/ |
Most of tests are already pass under PyPy (this means that C API used in Pillow is more or less compatible with cpyext):
I also think Pillow could be already quite fast under PyPy because most of time is spent in C code doing image operations - wrapping/unwrapping objects shouldn't be a bottleneck for most Pillow use cases. |
This is not true. People all the time do stuff like write a list of values into image or manipulate it pixel by pixel and come later complaining that it's slow. |
Looks good on
|
Wow |
I've done a lot of testing, the biggest problem I found is that the "pixel access object" is simply to slow under PyPy, close to useless. The workaround I found was to use the raw pixeldata (as string, array or list), and then change/read the pixels, then convert it back to a PIL-image again (image.fromstring). This was quite fast, actually faster than CPython in many cases, but it's a really clumsy solution, using struct/or array module... An example of iterating over 1000x1000 pixels, and getting the pixelval of each pixel: from PIL import Image
def py_optimal(im):
W,H = im.size
pix = im.load()
for x in range(W):
for y in xrange(H):
F = pix[x,y]
# do something... from PIL import Image
from array import array
def pypy_optimal(im):
W,H = im.size
pix = array('B', im.convert("RGB").tostring('raw'))
i = 0
for x in range(W):
for y in range(H):
r = pix[i+0]
g = pix[i+1]
b = pix[i+2]
i += 3
# do something.. So i tested these two ways of READING the pixels 50 times to get an accurate timing... The first solutions (standard way to do it), time used was:
The workaround I use: Time:
You should really optimizing this for PyPy! |
Thanks for the comment, you are welcome to send a pull request |
PyPy is kind of a moving target for optimization purposes. (there's a 2.0 out now). I'm guessing that the issue is crossing the c/python boundary inside a tight loop, and building a return value each time. It's likely that the c extension in C python has a much lower impedance mismatch. |
On Mon, May 20, 2013 at 10:48 PM, wiredfool notifications@git.luolix.topwrote:
CPython C API is a compatibility layer that is and always will be very |
A moving target = quickly progressing. The pixel access object is pretty simple. My suspicion is that if it was pure python, it might be slow in CPython, but probably fast in PyPy. As it is, it's the opposite as a c api object. Unfortunately, the pixel_access_object is only a thin shim on the Access.c get_pixel/put_pixel methods, and I don't see a way to get to the pixel data from python, without dropping to C somewhere. There might be a way with buffer objects, but I'm not sure that the image stores it's data in a way appropriate for that. |
On Mon, May 20, 2013 at 11:28 PM, wiredfool notifications@git.luolix.topwrote:
If you need to call, call it with cffi (C functions directly) instead of C |
On Tue, May 21, 2013 at 12:12 AM, Maciej Fijalkowski fijall@gmail.comwrote:
to be perfectly clear - I doubt there is no way to access raw data one |
No is probably an incorrect term. But from my quick reading of the code, it appears that the image may be stored in multiple chunks, which would complicate access from just the pointer. |
Suggested by Maciej Fijalkowski on Twitter https://twitter.com/fijall/status/309321486815088640
The text was updated successfully, but these errors were encountered: