----Security_Multipart0(Fri_Feb_14_06:02:42_2003_652)-- Content-Type: Multipart/Mixed; boundary="--Next_Part(Fri_Feb_14_06:02:42_2003_595)--" Content-Transfer-Encoding: 7bit ----Next_Part(Fri_Feb_14_06:02:42_2003_595)-- Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit I have an idea that may result in significant optimization of python. However, I have an incomplete understanding of what's involved, and I haven't had enough time to puzzle out enough of Python's internals to write up a full PEP describing this. Method calls appear are a full 20% slower (simple benchmark included) than function calls, and Python function calls are already pretty slow. By my understanding, one of the reasons for the difference is that if you have a method call like this: a = A() a.b() what's really happening is something along the lines of: temp = new.instancemethod(getattr(a.__class__, "b"), a, A) temp() free(temp) This causes an unnecessary memory allocation: since the instancemethod object is immediately being created, then called, then garbage collected. Looking at the output of dis.dis, I can see there are also 3 bytecodes being evaluated rather than 1. My proposal is to treat method calls as syntactically different from function calls. Rather than x.y() being completely synonymous with getattr(x, "y")(), it could be analogous to 'x.y = z' or 'del x.y'. For symmetry with these statement types, the new bytecode could be called CALL_ATTR. I think this is an important thing to consider as systems like Zope and Twisted move towards using component models and Interfaces in Python. The fact that direct function calls are so much faster puts efficiency directly at odds with structured flexibility. With a method call primitive comparable to function calls, most python code, especially in systems that make heavy use of inter-object communication patterns, would immediately get as much as a 15% speed boost. CALL_ATTR should be implementable with no impact on existing python code, except bytecode hacks. It should be possible to retain a fully backwards-compatible __getattr__ method, for places where method objects are used (including the C API). Likewise, the default __callattr__ could be set up to first check if __getattr__ is defined, then the instance's dictionary or __slots__. For additional speed gains, new-object-model classes could set '__fast_methods__ = True' and gain a semantic distinction between __getattr__ and __callattr__. Better still, I think that Jython could use the subtle semantic change to make Java reflection less expensive. (Java's `new' is more expensive than C's `malloc', after all.) I have a sneaking suspicion that this would also be good for security purposes. I haven't yet come up with a specific case where this is a big deal, but I think capability-style data-hiding would be simplified if filtering method-calls were different from filtering attributes. I hope this idea is useful to some of you, -- | <`'> | Glyph Lefkowitz: Traveling Sorcerer | | < _/ > | Lead Developer, the Twisted project | | < ___/ > | http://www.twistedmatrix.com | ----Next_Part(Fri_Feb_14_06:02:42_2003_595)-- Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="methods.py" import time class A: def b(self): pass def b(self): pass a = A() def wallclock(f): then = time.time() f() now = time.time() elapsed = now - then return elapsed NCALLS = 1000000 def methods(): for x in xrange(NCALLS): a.b() def functions(): for x in xrange(NCALLS): b(a) print wallclock(methods) print wallclock(functions) ----Next_Part(Fri_Feb_14_06:02:42_2003_595)-- Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="results.txt" % python2.0 methods.py 1.85362696648 1.47611200809 % python2.1 methods.py 1.21098303795 0.972733020782 % python2.2 methods.py 1.15857589245 0.914402961731 % jython methods.py 63.396000027656555 51.51300001144409 ----Next_Part(Fri_Feb_14_06:02:42_2003_595)---- ----Security_Multipart0(Fri_Feb_14_06:02:42_2003_652)-- Content-Type: application/pgp-signature Content-Transfer-Encoding: 7bit -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.1 (GNU/Linux) iD8DBQA+TNrkvVGR4uSOE2wRAiwFAKCdjtbXx1yz4QN0uX4JOTsQwTQf/gCeOemO s2R3ZfWC3R4TREI8VULt/2o= =+8zq -----END PGP SIGNATURE----- ----Security_Multipart0(Fri_Feb_14_06:02:42_2003_652)----
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4