[issue1518] Fast globals/builtins access (patch)

2007-11-29 Thread Neil Toronto

Neil Toronto added the comment:

Christian: Thanks for that, I'll have to remember DEBUG_LEAK in the
future. :)

It looks like it may be acting correctly since there *is* now a
fastglobals object that needs collecting, and also a new tuple built
from co_names + "__builtins__". I don't know why it wouldn't collect
those in the shell, though. The shell does create a new stack frame for
every command (where a function's commands are all run in a single stack
frame), but I don't know why that would matter. I'll look further into it.

Chris: The build problems should be fixed in the next patch. Thanks for
spending so much time on benchmarking this.

Regarding PyEval_EvalCode creating a PyFastGlobalsObject: I'm not sure
whether it's right thing to do, but I think it is. PyEval_EvalCode gets
called for eval, exec, running an imported module's code, and everything
in the interactive prompt - basically, running any code that's not in a
function or generator. (I think that covers everything.) It seems like
the patch has PyEval_EvalCode doing the right thing in general, but it
may suffer a bit in benchmarks.

__
Tracker <[EMAIL PROTECTED]>
<http://bugs.python.org/issue1518>
__
___
Python-bugs-list mailing list 
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue1560] PATCH: Attribute lookup caching

2007-12-05 Thread Neil Toronto

New submission from Neil Toronto:

I've attached a patch to accelerate type and instance lookups using a
specialized cache. It includes a benchmarking script (fastattr_test.py)
that tests both successful and failing lookups on list, dict and tuple,
and a simple, deep hierarchy. Benchmark results are here:

http://spreadsheets.google.com/ccc?key=pHIJrYc_pnIUpTm6QSG2gZg&hl=en_US

Everything tested in fastattr_test.py is faster except list.__init__ and
list().__init__ (and I haven't got a clue why, so some pointers would be
nice). Pybench is faster overall. TryRaiseExcept is faster for some
non-obvious reason. CreateNewInstances is a little slower, which I'll
discuss in a bit. Setting type attributes is slower, but I haven't
benchmarked that yet. It may not happen often enough that we care as
long as it's not noticeably slow in general usage.

In benchmarks the patch does a little slower, it may be in part because
I removed a manually inlined _PyType_Lookup from
PyObject_GenericGetAttr. Something like it can be put back if it needs
to be.

It works in a fairly obvious way. Every type has a tp_cache, which is a
custom dict type that caches the first value in a type dict in the MRO
for a given name. Lazy cached lookups are done via
_PyType_CachingLookup, which is a drop-in replacement for
_PyType_Lookup. The only way to set an attribute on a type is via its
setattr, so type's setattr notifies subclasses to invalidate specific
cache entries.

The cache dict is custom for two reasons:

1. The regular dict is a little slower because it's more general. The
custom dict is restricted to string-exact keys (types fall back to no
caching if this constraint is violated). Because it's internal to
typeobject.c, it's safe for lookups to return entry pointers rather than
values, so lookups only have to be done once, even on cache misses.

2. Caching missing attributes is crucial for speed on instance attribute
lookups. Both type and metatype instances check all the way through the
MRO for a descriptor before even trying to find an attribute. It's
usually missing. Having to go through the cache machinery to find a
missing attribute for every attribute lookup is expensive. However,
storing all missing attribute queries in the cache is bad - it can grow
unboundedly through hasattr(inst, ) calls.

What's needed is a dict that knows that some of its entries are
transient and doesn't copy them over on resize. It wasn't clear how to
implement that efficiently with a regular dict (I suspect it's not
possible), so I created a new dict type that considers entries transient
(meaning the attribute is missing) when me_value == NULL.

This is also very good for failing hasattr(...) calls and
try...inst.method()...except style duck typing.

Now, about the CreateNewInstances benchmark. It creates three classes
with __init__ methods that assign a few attributes. The missing
descriptors are cached, and then the cache is resized, which clears the
cached missing descriptors. Increasing the minimum cache size from 4 to
8 clears up the problem. However, for any class, SOME minimum cache size
will properly cache missing descriptors and some other one won't.

I have some solutions for this floating around in my head, which I'll
try shortly. (One idea is for missing attributes, if they're not missing
on the *instance*, to be permanent in the cache.) But I'd like to get
this patch off my hard drive and into other people's hands for testing,
poking, prodding, and getting feedback on what's going right and what's not.

--
components: Interpreter Core
files: fastattr-0.patch.txt
messages: 58229
nosy: ntoronto
severity: normal
status: open
title: PATCH: Attribute lookup caching
versions: Python 2.6
Added file: http://bugs.python.org/file8883/fastattr-0.patch.txt

__
Tracker <[EMAIL PROTECTED]>
<http://bugs.python.org/issue1560>
__Index: Include/dictobject.h
===
--- Include/dictobject.h(revision 59362)
+++ Include/dictobject.h(working copy)
@@ -111,6 +111,8 @@
 PyAPI_FUNC(int) PyDict_Contains(PyObject *mp, PyObject *key);
 PyAPI_FUNC(int) _PyDict_Contains(PyObject *mp, PyObject *key, long hash);
 
+PyAPI_FUNC(int) PyDict_IsStringKeysOnly(PyObject *mp);
+
 /* PyDict_Update(mp, other) is equivalent to PyDict_Merge(mp, other, 1). */
 PyAPI_FUNC(int) PyDict_Update(PyObject *mp, PyObject *other);
 
Index: Include/object.h
===
--- Include/object.h(revision 59362)
+++ Include/object.h(working copy)
@@ -391,6 +391,7 @@
 PyAPI_FUNC(PyObject *) PyType_GenericNew(PyTypeObject *,
   PyObject *, PyObject *);
 PyAPI_FUNC(PyObject *) _PyType_Lookup(PyTypeObject *, PyObject *);
+PyAPI_F

[issue1700288] Armin's method cache optimization updated for Python 2.6

2007-12-06 Thread Neil Toronto

Neil Toronto added the comment:

Attribute access that happens only once or very infrequently probably
shouldn't go through the cache machinery - it'll only slow things down.
(Updating slots for example.) Maybe _PyType_Lookup should remain the
same, with _PyType_CachingLookup added for attribute access via
type/instance getattr.

_
Tracker <[EMAIL PROTECTED]>
<http://bugs.python.org/issue1700288>
_
___
Python-bugs-list mailing list 
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue1700288] Armin's method cache optimization updated for Python 2.6

2007-12-06 Thread Neil Toronto

Neil Toronto added the comment:

I've attached the microbenchmarks I was using for my own version of
attribute caching. For list, tuple, dict, and a deep hierarchy, it tests
accessing type attributes (cls.__class__), class attributes
(cls.__init__), class attributes via instance (inst.__class__), and
instance attributes (inst.__init__), using LOAD_ATTR and hasattr. It
also tests hasattr with missing attributes.

--
nosy: +ntoronto
Added file: http://bugs.python.org/file8887/fastattr_test.py

_
Tracker <[EMAIL PROTECTED]>
<http://bugs.python.org/issue1700288>
_#!/usr/bin/python

import timeit, random, time, sys

MULTIPLIER = 1


class A(object):
	def __init__(self, *args):
		pass

class B(A): pass

class C(B): pass

class D(C): pass

class E(D): pass

class F(E): pass

class G(F): pass

class H(G):
	def __init__(self):
		pass

class I(H): pass


def test_init(tmp):
	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__


def test_class(tmp):
	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__
	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__
	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__
	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__
	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__
	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__
	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__
	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__
	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__
	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__
	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__
	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__
	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__
	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__
	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__
	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__
	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__
	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__
	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__
	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__


def test_has_init(tmp):
	hasattr(tmp, '__init__'); hasattr(tmp, '__init__')
	hasattr(tmp, '__init__'); hasattr(tmp, '__init__')
	hasattr(tmp, '__init__'); hasattr(tmp, '__init__')
	hasattr(tmp, '__init__'); hasattr(tmp, '__init__')
	hasattr(tmp, '__init__'); hasattr(tmp, '__init__')
	hasattr(tmp, '__init__'); hasattr(tmp, '__init__')
	hasattr(tmp, '__init__'); hasattr(tmp, '__init__')
	hasattr(tmp, '__init__'); hasattr(tmp, '__init__')
	hasattr(tmp, '__init__'); hasattr(tmp, '__init__')
	hasattr(tmp, '__init__'); hasattr(tmp, '__init__')
	hasattr(tmp, '__init__'); hasattr(tmp, '__init__')
	hasattr(tmp, '__init__'); hasattr(tmp, '__init__')
	hasattr(tmp, '__init__'); hasattr(tmp, '__init__')
	hasattr(tmp, '__init__'); hasattr(tmp, '__init__')
	hasattr(tmp, '__init__'); hasattr(tmp, '__init__

[issue1568] PATCH: Armin's attribute lookup caching for 3.0

2007-12-07 Thread Neil Toronto

New submission from Neil Toronto:

This is a half-port of the patches in #1685986 and #1700288 to Python
3.0. Speedups are about the same as in those patches applied to their
respective Python versions for minibenchmarks (included in the patch as
fastattr_test_py3k.py): 5%-30% or more depending on how deep the class
hierarchy is. Pybench takes 4% less time on my system, and pystone takes
6% less time.

(Pybench would do better, but SpecialClassAttribute runs long and spends
half its time setting class attributes.)

The main difference between this and the previous patches is that 3.0's
simplifications allow a smaller footprint and make it easier to analyze
its correctness. Specifically, the fact that every object in the MRO
must be a type allows us to assume that every attribute lookup is
cacheable, and allows integration into the update_subclasses mechanism
when attributes are set. The lack of compiled extension modules means
there is no flag to check to see whether a type object supports caching.

--
components: Interpreter Core
files: python30-attrcache.diff
messages: 58274
nosy: ntoronto
severity: normal
status: open
title: PATCH: Armin's attribute lookup caching for 3.0
type: rfe
versions: Python 3.0
Added file: http://bugs.python.org/file8889/python30-attrcache.diff

__
Tracker <[EMAIL PROTECTED]>
<http://bugs.python.org/issue1568>
__Index: Python/pythonrun.c
===
--- Python/pythonrun.c	(revision 59400)
+++ Python/pythonrun.c	(working copy)
@@ -501,6 +501,9 @@
 
 	/* Cleanup Unicode implementation */
 	_PyUnicode_Fini();
+	
+	/* Report counts of attribute cache hits/misses (if enabled) */
+	PyType_Fini();
 
 	/* reset file system default encoding */
 	if (!Py_HasFileSystemDefaultEncoding) {
Index: Include/object.h
===
--- Include/object.h	(revision 59400)
+++ Include/object.h	(working copy)
@@ -373,6 +373,9 @@
 	PyObject *tp_subclasses;
 	PyObject *tp_weaklist;
 	destructor tp_del;
+	/* Unique cache ID per type, assigned when bases change (see
+	   mro_internal) */
+	PY_LONG_LONG tp_cache_id;
 
 #ifdef COUNT_ALLOCS
 	/* these must be last and never explicitly initialized */
Index: Include/pythonrun.h
===
--- Include/pythonrun.h	(revision 59400)
+++ Include/pythonrun.h	(working copy)
@@ -141,6 +141,7 @@
 PyAPI_FUNC(void) PyBytes_Fini(void);
 PyAPI_FUNC(void) PyFloat_Fini(void);
 PyAPI_FUNC(void) PyOS_FiniInterrupts(void);
+PyAPI_FUNC(void) PyType_Fini(void);
 
 /* Stuff with no proper home (yet) */
 PyAPI_FUNC(char *) PyOS_Readline(FILE *, FILE *, char *);
Index: fastattr_test_py3k.py
===
--- fastattr_test_py3k.py	(revision 0)
+++ fastattr_test_py3k.py	(revision 0)
@@ -0,0 +1,265 @@
+#!/usr/bin/python
+
+import timeit, random, time, sys
+
+MULTIPLIER = 1
+
+
+class A(object):
+	def __init__(self, *args):
+		pass
+
+class B(A): pass
+
+class C(B): pass
+
+class D(C): pass
+
+class E(D): pass
+
+class F(E): pass
+
+class G(F): pass
+
+class H(G):
+	def __init__(self):
+		pass
+
+class I(H): pass
+
+
+def test_init(tmp):
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+
+
+def test_class(tmp):
+	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__
+	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__
+	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__c

[issue1568] PATCH: Armin's attribute lookup caching for 3.0

2007-12-07 Thread Neil Toronto

Neil Toronto added the comment:

This patch adds the ability to invalidate all of a subclasses' cache
entries upon setattr rather than updating just one cache entry. It's not
clear which of these is the Right Thing To Do, so I've made it an #ifdef
for now. It defaults to updating.

Added file: http://bugs.python.org/file8891/python30-attrcache-1.diff

__
Tracker <[EMAIL PROTECTED]>
<http://bugs.python.org/issue1568>
__Index: Python/pythonrun.c
===
--- Python/pythonrun.c	(revision 59400)
+++ Python/pythonrun.c	(working copy)
@@ -501,6 +501,9 @@
 
 	/* Cleanup Unicode implementation */
 	_PyUnicode_Fini();
+	
+	/* Report counts of attribute cache hits/misses (if enabled) */
+	PyType_Fini();
 
 	/* reset file system default encoding */
 	if (!Py_HasFileSystemDefaultEncoding) {
Index: Include/object.h
===
--- Include/object.h	(revision 59400)
+++ Include/object.h	(working copy)
@@ -373,6 +373,9 @@
 	PyObject *tp_subclasses;
 	PyObject *tp_weaklist;
 	destructor tp_del;
+	/* Unique cache ID per type, assigned when bases change (see
+	   mro_internal) */
+	PY_LONG_LONG tp_cache_id;
 
 #ifdef COUNT_ALLOCS
 	/* these must be last and never explicitly initialized */
Index: Include/pythonrun.h
===
--- Include/pythonrun.h	(revision 59400)
+++ Include/pythonrun.h	(working copy)
@@ -141,6 +141,7 @@
 PyAPI_FUNC(void) PyBytes_Fini(void);
 PyAPI_FUNC(void) PyFloat_Fini(void);
 PyAPI_FUNC(void) PyOS_FiniInterrupts(void);
+PyAPI_FUNC(void) PyType_Fini(void);
 
 /* Stuff with no proper home (yet) */
 PyAPI_FUNC(char *) PyOS_Readline(FILE *, FILE *, char *);
Index: fastattr_test_py3k.py
===
--- fastattr_test_py3k.py	(revision 0)
+++ fastattr_test_py3k.py	(revision 0)
@@ -0,0 +1,265 @@
+#!/usr/bin/python
+
+import timeit, random, time, sys
+
+MULTIPLIER = 1
+
+
+class A(object):
+	def __init__(self, *args):
+		pass
+
+class B(A): pass
+
+class C(B): pass
+
+class D(C): pass
+
+class E(D): pass
+
+class F(E): pass
+
+class G(F): pass
+
+class H(G):
+	def __init__(self):
+		pass
+
+class I(H): pass
+
+
+def test_init(tmp):
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+	tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__; tmp.__init__
+
+
+def test_class(tmp):
+	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__
+	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__
+	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__
+	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__
+	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__
+	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__
+	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__
+	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__
+	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__
+	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__
+	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__
+	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__
+	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__
+	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__
+	tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__; tmp.__class__
+	tmp.__class__; tmp.__

[issue1560] PATCH: Attribute lookup caching

2007-12-10 Thread Neil Toronto

Neil Toronto added the comment:

Yes, as well #1700288 (Armin's attribute lookup caching patch ported to
2.6) or #1685986 (Armin's original for 2.4), or whatever Raymond finds
most convenient.

__
Tracker <[EMAIL PROTECTED]>
<http://bugs.python.org/issue1560>
__
___
Python-bugs-list mailing list 
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue1560] PATCH: Attribute lookup caching

2007-12-10 Thread Neil Toronto

Neil Toronto added the comment:

Sorry - I'll be more clear. I'd love to see 2.6 get attribute lookup
caching, and Kevin's port (#1700288) of Armin's original 2.4 patch
(#1685986) does that for 2.6. #1685986 (2.4) should be closed and
#1700288 (2.6) should remain open. But Raymond has indicated that he's
currently working on #1685986 - I think for 2.6, but it's not clear.

__
Tracker <[EMAIL PROTECTED]>
<http://bugs.python.org/issue1560>
__
___
Python-bugs-list mailing list 
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue1568] PATCH: Armin's attribute lookup caching for 3.0

2008-01-16 Thread Neil Toronto

Neil Toronto added the comment:

Well horse pucky. I plum forgot about deletes.

I've attached an update that properly clears the cache entry for the
deleted attribute for all non-shadowing subclasses. (It was a small
change.) Undef'ing ATTRCACHE_SETATTR_INVALIDATES should work now.

Re: different from 2.6: It takes advantage of the lack of "classic"
classes. That makes some things a lot easier. Also, I was looking into
updating cache entries to see if it would be faster than invalidating
all the entries for a type, among other improvements. FWIW, updating
cache entries is a little faster on my box.

Also: This may have the same problem with test_ctypes'
test_incomplete.py as #1700288 did, though I haven't seen any ctypes
tests fail.

Added file: http://bugs.python.org/file9189/python30-attrcache-2.diff

__
Tracker <[EMAIL PROTECTED]>
<http://bugs.python.org/issue1568>
__
___
Python-bugs-list mailing list 
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue1568] PATCH: Armin's attribute lookup caching for 3.0

2008-01-23 Thread Neil Toronto

Neil Toronto added the comment:

There's nothing it tests that standard unit tests don't, so it shouldn't
stick around as a unit test. I used it to time different types of
attribute lookups and left it in as an optimization aid.

The main test groups are '.' access, successful hasattr (returns True),
and failing hasattr (returns False). For each group it prints a header
and then four test cases for each test class: metaclass attribute access
(class.__class__), class attribute access (class.__init__), class
attribute access via an instance (class().__class__), and instance
attribute access (class().__init__). The test classes include a few
built-ins and the classes of a made-up deep hierarchy.

The main thing to notice is that, when you run this using the patched
source, every number is no larger than when you run it using the trunk,
and most are smaller.

__
Tracker <[EMAIL PROTECTED]>
<http://bugs.python.org/issue1568>
__
___
Python-bugs-list mailing list 
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com