Re: [pypy-dev] Question about extension support
Your C-extensions come all bundled up with a whole lot of gorp which is designed to make them play nicely in a ref-counting environment. Ref counting is a very slow way to do GC. Sometimes -- really, really, really hideously slow. You are sometimes _way_ better off writing python code instead -- pypy with the jit turned off outperforms CPython purely on the benefits of not doing ref-counting, and pypy really needs the jit to be fast. There is a bit of conceptual confusion here -- on the one hand, because C extensions often were written for reasons of performance when compared to CPython, there is a tendency to believe that C-extensions are, pretty much by definition fast. And the other thing is a sort of reflexive belief that 'if it is in C (or C++) then it has to be fast'. Both of these ideas are wrong. A whole lot of C extensions are actually really, really slow. They are just faster than CPython -- or perhaps 'faster than CPython was when I wrote this thing' which isn't, after all, that hard a target to meet. When PyPy finds a C extension which is working very hard to pretend it is a set of Python objects that can be refcounted, it isn't brilliant enough to be able to throw away all the ref-counting fakery, intuit what the code here really is trying to do here, and just run that bit. That's too hard. Instead it decides to play along with the ref-counting faking. So we are at 'watch the elephant tap-dance' time ... it doesn't have to do a very good (read fast) job at this, it is amazing that it does it at all. Laura
Hi Laura, On 26 March 2014 23:29, Laura Creighton <lac@openend.se> wrote:
really, really hideously slow. You are sometimes _way_ better off writing python code instead -- pypy with the jit turned off outperforms CPython purely on the benefits of not doing ref-counting, and pypy really needs the jit to be fast.
That detail is wrong. PyPy with the JIT turned off is 1.5x to 2x slower than CPython. (The reason is just the higher level of RPython versus hand-optimized C.) It is a common misconception to blame reference counting for the general slowness of standard interpreters of Python-like languages; I've seen it a few times in various contexts. But it's wrong: manual reference counting as in CPython doesn't cost much. This is probably because the reference counting increment/decrement end up as a very small fraction of the total runtime in this case. Also, the malloc() implementation used probably helps (it is very close to the one for the standard malloc() on Linux, which is really efficient for a lot of usage patterns). On the other hand, the reason PyPy doesn't include refcounting is that it's not reasonable at the level of the RPython implementation. Our RPython code assumes a GC *all the time*, e.g. when dealing with internal lists; by contrast, the CPython implementation assumes no GC and tries hard to put everything as stack objects, only occasionally "giving up" and using a malloc, like it is common in C. So incref/decref "everywhere in PyPy" means at many, many more places than "everywhere in CPython". In PyPy it is enough to kill performance completely (as we measured a long time ago). So I would say that the difference between refcounting and a "real GC" is that the latter scales nicely to higher levels of memory pressure than refcounting; but refcounting is fine if you can manually optimize where increfs are needed and where they are not, and if you manually avoid creating garbage as much as possible. A bientôt, Armin.
Hi all, On Fri, Mar 28, 2014 at 8:51 AM, Armin Rigo <arigo@tunes.org> wrote:
Hi Laura,
On 26 March 2014 23:29, Laura Creighton <lac@openend.se> wrote:
really, really hideously slow. You are sometimes _way_ better off writing python code instead -- pypy with the jit turned off outperforms CPython purely on the benefits of not doing ref-counting, and pypy really needs the jit to be fast.
That detail is wrong. PyPy with the JIT turned off is 1.5x to 2x slower than CPython. (The reason is just the higher level of RPython versus hand-optimized C.)
It is a common misconception to blame reference counting for the general slowness of standard interpreters of Python-like languages; I've seen it a few times in various contexts. But it's wrong: manual reference counting as in CPython doesn't cost much. This is probably because the reference counting increment/decrement end up as a very small fraction of the total runtime in this case. Also, the malloc() implementation used probably helps (it is very close to the one for the standard malloc() on Linux, which is really efficient for a lot of usage patterns).
On the other hand, the reason PyPy doesn't include refcounting is that it's not reasonable at the level of the RPython implementation. Our RPython code assumes a GC *all the time*, e.g. when dealing with internal lists; by contrast, the CPython implementation assumes no GC and tries hard to put everything as stack objects, only occasionally "giving up" and using a malloc, like it is common in C. So incref/decref "everywhere in PyPy" means at many, many more places than "everywhere in CPython". In PyPy it is enough to kill performance completely (as we measured a long time ago).
This is a really interesting discussion, thanks for spelling it out the details so clearly. Did the measurements you refer to get published anywhere? Thanks, Sarah -- Sarah Mount, Senior Lecturer, University of Wolverhampton website: http://www.snim2.org/ twitter: @snim2
Hi Sarah, On 28 March 2014 11:08, Sarah Mount <mount.sarah@gmail.com> wrote:
This is a really interesting discussion, thanks for spelling it out the details so clearly. Did the measurements you refer to get published anywhere?
Yes, in https://bitbucket.org/pypy/extradoc/raw/tip/eu-report/D07.1_Massive_Parallel... , section Reference counting. A bientôt, Armin.
participants (3)
-
Armin Rigo
-
Laura Creighton
-
Sarah Mount