classification
Title: speed up isinstance and issubclass for the usual cases
Type: performance Stage: resolved
Components: Interpreter Core Versions: Python 3.5
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: georg.brandl, ncoghlan, pitrou, python-dev, vstinner, yselivanov
Priority: normal Keywords: patch

Created on 2014-10-02 11:39 by georg.brandl, last changed 2014-10-04 07:07 by georg.brandl. This issue is now closed.

Files
File name Uploaded Description Edit
pyobject_issubclass_isinstance_speedup.patch georg.brandl, 2014-10-02 11:39 review
pyobject_issubclass_isinstance_speedup_v2.patch georg.brandl, 2014-10-03 07:00 review
Messages (7)
msg228218 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2014-10-02 11:39
With the introduction of ABCs, PyObject_IsInstance (and for this issue, everything is also valid for PyObject_IsSubclass) has to check for a type's __instancecheck__ before falling back to the built-in behavior.

However, the "type" type has an __instancecheck__ method (that calls the built-in behavior too), probably for consistency on the Python side.

This means that the fast path is never taken, and every isinstance() call is slowed down unnecessarily.

This patch introduces a new fast path by checking for PyType_Type exactly before looking up the __instancecheck__.

It also introduces a check for exact match in PyObject_IsSubclass() analogous to one that is already present in PyObject_IsInstance().  Note that this will break __subclasscheck__ implementations that would deny issubclass(C, C).

This patch is not only useful for speeding up isinstance() and issubclass() calls, but also has other effects such as not slowing down the improvement of issue #12029.
msg228306 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2014-10-03 07:00
Addressing review comments.
msg228308 - (view) Author: Roundup Robot (python-dev) Date: 2014-10-03 07:32
New changeset 4f33a4a2b425 by Georg Brandl in branch 'default':
Closes #22540: speed up PyObject_IsInstance and PyObject_IsSubclass in the common case that the second argument has metaclass "type".
https://hg.python.org/cpython/rev/4f33a4a2b425
msg228311 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2014-10-03 09:02
A buildbot is failing since your change.

http://buildbot.python.org/all/builders/AMD64%20Debian%20root%203.x/builds/1261/steps/test/logs/stdio

======================================================================
ERROR: test_decimal_fraction_comparison (test.test_decimal.CUsabilityTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/root/buildarea/3.x.angelico-debian-amd64/build/Lib/test/test_decimal.py", line 1711, in test_decimal_fraction_comparison
    self.assertLess(D(0), F(1,9999999999999999999999999999999999999))
  File "/root/buildarea/3.x.angelico-debian-amd64/build/Lib/unittest/case.py", line 1174, in assertLess
    if not a < b:
TypeError: unorderable types: decimal.Decimal() < Fraction()

======================================================================
FAIL: test_abc (test.test_decimal.CPythonAPItests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/root/buildarea/3.x.angelico-debian-amd64/build/Lib/test/test_decimal.py", line 2404, in test_abc
    self.assertTrue(issubclass(Decimal, numbers.Number))
AssertionError: False is not true

======================================================================
ERROR: test_mixed_comparisons (test.test_numeric_tower.ComparisonTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/root/buildarea/3.x.angelico-debian-amd64/build/Lib/test/test_numeric_tower.py", line 173, in test_mixed_comparisons
    self.assertLess(first, second)
  File "/root/buildarea/3.x.angelico-debian-amd64/build/Lib/unittest/case.py", line 1174, in assertLess
    if not a < b:
TypeError: unorderable types: decimal.Decimal() < Fraction()
msg228313 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2014-10-03 09:09
The test_decimal failure can be reproduced using:

  ./python  -m test -W test_datetime test_decimal
msg228317 - (view) Author: Roundup Robot (python-dev) Date: 2014-10-03 09:28
New changeset 6cfe929d1de5 by Antoine Pitrou in branch 'default':
Make test_datetime a better citizen (issue #22540)
https://hg.python.org/cpython/rev/6cfe929d1de5
msg228339 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2014-10-03 16:56
Thanks for fixing! I did run "make test" locally, but that did not produce the failure.
History
Date User Action Args
2014-10-04 07:07:00georg.brandlsetstatus: open -> closed
resolution: fixed
2014-10-03 16:56:14georg.brandlsetmessages: + msg228339
2014-10-03 09:28:39python-devsetmessages: + msg228317
2014-10-03 09:09:58pitrousetmessages: + msg228313
2014-10-03 09:02:24vstinnersetstatus: closed -> open
resolution: fixed -> (no value)
messages: + msg228311
2014-10-03 07:32:48python-devsetstatus: open -> closed

nosy: + python-dev
messages: + msg228308

resolution: fixed
stage: patch review -> resolved
2014-10-03 07:10:26vstinnersetnosy: + vstinner
2014-10-03 07:00:54georg.brandlsetfiles: + pyobject_issubclass_isinstance_speedup_v2.patch

messages: + msg228306
2014-10-02 22:54:50yselivanovsetnosy: + yselivanov
2014-10-02 11:40:06georg.brandllinkissue12029 dependencies
2014-10-02 11:39:12georg.brandlcreate