Skip to content

Instantly share code, notes, and snippets.

@denik
Last active December 10, 2015 09:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save denik/4412582 to your computer and use it in GitHub Desktop.
Save denik/4412582 to your computer and use it in GitHub Desktop.
Unexpectedly bad performance of stackless and greenlet on PyPy
# according to this benchmark stackless.channel is 100x slower on PyPy compared to Stackless
"""
Stackless result:
$ stackless2.7-static test_channel_stackless.py
1000000 send took 0.397s
Stackless version:
$ stackless2.7-static
Python 2.7.1 Stackless 3.1b3 060516 (release27-maint, Oct 30 2011, 11:49:35)
[GCC 4.1.2] on linux2
PyPy result:
$ ~/src/pypy-2.0-beta1/bin/pypy test_channel_stackless.py
1000000 send took 49.354s
PyPy version:
$ ~/src/pypy-2.0-beta1/bin/pypy
Python 2.7.3 (7e4f0faa3d51, Nov 16 2012, 16:56:51)
[PyPy 2.0.0-beta1 with GCC 4.4.3] on linux2
"""
import stackless
from time import time
N = 1000 * 1000
count = N
def func(ch):
global count
while count > 0:
ch.send(ch.receive())
count -= 1
ch = stackless.channel()
start = time()
stackless.tasklet(func)(ch)
ch.send(True)
stackless.tasklet(func)(ch)
stackless.run()
took = time() - start
assert not count, count
print '%s send took %.3fs' % (N, took)
# according to this benchmark greenlet is 20x times slower on PyPy than it is on CPython
"""
CPython result:
$ python test_switch.py
1000000 switches took 0.404s
CPython version:
$ python
Python 2.7.3 (default, Aug 1 2012, 05:16:07)
[GCC 4.6.3] on linux2
PyPy result:
$ ~/src/pypy-2.0-beta1/bin/pypy test_switch.py
1000000 switches took 9.338s
PyPy version:
$ ~/src/pypy-2.0-beta1/bin/pypy
Python 2.7.3 (7e4f0faa3d51, Nov 16 2012, 16:56:51)
[PyPy 2.0.0-beta1 with GCC 4.4.3] on linux2
"""
import greenlet
from time import time
N = 1000 * 1000
count = N
def func(next):
global count
while count > 0:
next.switch()
count -= 1
g1 = greenlet.greenlet(func)
main = greenlet.getcurrent()
start = time()
while count > 0:
g1.switch(main)
count -= 1
took = time() - start
assert count <= 0, count
print ('%s switches took %.3fs' % (N, took))
@tlynn
Copy link

tlynn commented Jan 19, 2013

"There are a few things that did not make it to the 2.0 beta 1, which are being actively worked on. Greenlets support in the JIT is one that we would like to have before 2.0 final."

http://morepypy.blogspot.co.uk/2012/11/pypy-20-beta-1.html

@schmir
Copy link

schmir commented Mar 12, 2013

using pypy's jitframe-on-heap branch pypy is a bit faster on my machine:

$ ./pypy-jitframe-on-heap-2013-02-06/bin/pypy test_switch.py
1000000 switches took 0.209s
$ python test_switch.py                                     
1000000 switches took 0.361s

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment