[Patches] [ python-Patches-423181 ] small speedup in object rich comparisons
noreply@sourceforge.net
noreply@sourceforge.net
Fri, 11 May 2001 06:36:55 -0700
Patches item #423181, was updated on 2001-05-10 15:39
You can respond by visiting:
http://sourceforge.net/tracker/?func=detail&atid=305470&aid=423181&group_id=5470
Category: core (C code)
Group: None
Status: Open
Resolution: Accepted
Priority: 5
Submitted By: Jeremy Hylton (jhylton)
>Assigned to: Jeremy Hylton (jhylton)
Summary: small speedup in object rich comparisons
Initial Comment:
One thing that jumped out at me when I profiled
test_mutant is how often PyErr_Format() was called. It
ends up that the rich comparisons code does a lot of
lookups for methods like __lt__ and __gt__ and usually
doesn't find them. It uses PyObject_GetAttr() for the
lookups, so it goes to the expense of creating a Python
string with a nice error message.
This patch uses the internal instance_getattr2 when it
can, i.e. when the instance doesn't define
__getattr__. This function won't find __dict__ or
__class__, won't do rexec checks, won't call
__getattr__, and (best of all) won't set an exception.
Unfortunately, test_mutants sees only a small speedup
as a result -- about six percent.
----------------------------------------------------------------------
Comment By: Tim Peters (tim_one)
Date: 2001-05-10 22:02
Message:
Logged In: YES
user_id=31435
Marked Accepted. I'd be happier with
1) A comment in the *code* explaining why instance_getattr2
is called.
2) assert(!PyErr_Occurred()) after getting back with a NULL
result (no cost in release builds, potentially helpful in
debug builds).
3) A general rewrite of the whole attribute lookup
mechanism that doesn't force anyone to pay for stuff they
later need to undo -- plus that never does string
comparisons.
I'll settle for #3 alone, though <wink>.
----------------------------------------------------------------------
Comment By: Tim Peters (tim_one)
Date: 2001-05-10 17:21
Message:
Logged In: YES
user_id=31435
Another odd thing: there are way more calls to
string_compare() than I would expect in this nearly string-
free program <wink>. One cause: half_richcompare has a
table of special operator names:
static char *name_op[] = {
"__lt__",
"__le__",
"__eq__",
"__ne__",
"__gt__",
"__ge__",
};
and does this at the start:
name = PyString_InternFromString(name_op[op]);
That *always* ends up calling PyDict_GetItem(), and then
string_compare() one or more times, for the obvious reason
(i.e., the interning work is wasted because it doesn't get
reflected back into the name_op table).
Interning isn't buying us anything for module attribute
lookups either, because module_getattr takes a char*
argument (i.e., this is another frequent cause of
string_compare() calls in this program, due to lots of
random.this() and random.that() calls, and they always end
up getting resolved via string_compare()).
----------------------------------------------------------------------
Comment By: Tim Peters (tim_one)
Date: 2001-05-10 16:32
Message:
Logged In: YES
user_id=31435
Cool! I'll check this out.
Another interesting thing about the test_mutants profile
was that it spent no measurable time at all in the dict
comparison code (dict_compare() + dict_richcompare() +
dict_equal() + characterize() times summed to 0) -- which
kinda explains why my efforts to speed those had no
measurable effect <wink/sigh>.
----------------------------------------------------------------------
You can respond by visiting:
http://sourceforge.net/tracker/?func=detail&atid=305470&aid=423181&group_id=5470