Repository navigation
Closed
Labels
interpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)type-featureA feature request or enhancementA feature request or enhancement
Description
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
assignee = None
closed_at = <Date 2010-10-23.19:09:16.110>
created_at = <Date 2010-09-04.22:11:29.637>
labels = ['interpreter-core', 'type-feature']
title = 'Make hash values the same width as a pointer (or Py_ssize_t)'
updated_at = <Date 2010-10-23.19:09:16.109>
user = 'https://github.com/pitrou'bugs.python.org fields:
activity = <Date 2010-10-23.19:09:16.109>
actor = 'loewis'
assignee = 'none'
closed = True
closed_date = <Date 2010-10-23.19:09:16.110>
closer = 'loewis'
components = ['Interpreter Core']
creation = <Date 2010-09-04.22:11:29.637>
creator = 'pitrou'
dependencies = []
files = ['19257', '19258', '19260', '19317', '19338', '19343']
hgrepos = []
issue_num = 9778
keywords = ['patch']
message_count = 52.0
messages = ['115617', '115618', '115619', '115626', '115639', '115656', '115657', '115695', '118789', '118820', '118823', '118953', '118954', '118955', '118959', '118968', '118972', '118980', '118982', '118983', '118987', '118994', '118995', '119000', '119001', '119011', '119015', '119017', '119019', '119020', '119025', '119029', '119030', '119034', '119043', '119044', '119058', '119077', '119079', '119080', '119124', '119265', '119411', '119415', '119442', '119443', '119446', '119453', '119456', '119464', '119465', '119468']
nosy_count = 14.0
nosy_names = ['lemburg', 'tim.peters', 'loewis', 'skip.montanaro', 'georg.brandl', 'rhettinger', 'jimjjewett', 'mark.dickinson', 'belopolsky', 'pitrou', 'casevh', 'ked-tao', 'benjamin.peterson', 'skrah']
pr_nums = []
priority = 'normal'
resolution = 'accepted'
stage = None
status = 'closed'
superseder = None
type = 'enhancement'
url = 'https://bugs.python.org/issue9778'
versions = ['Python 3.2', 'Python 3.3']Metadata
Metadata
Assignees
Labels
interpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)type-featureA feature request or enhancementA feature request or enhancement
Activity
pitrou commentedon Sep 4, 2010
Currently, Python produces hash values with fit in a C "long". This is fine at first sight, but in the context of dict and set implementations, it means that
A future-proof option would be to change all hash values to be of Py_ssize_t values rather than C longs. Either directly, or by defining a new dedicated alias Py_hash_t. This would also impact the ABI, I suppose.
pitrou commentedon Sep 4, 2010
As an example of padding behaviour (under Win64 with 32-bit longs and 64-bit pointers):
Python 3.2a1+ (py3k, Sep 4 2010, 22:50:10) [MSC v.1500 64 bit (AMD64)] on win32
rhettinger commentedon Sep 4, 2010
+1 for PyObject_Hash returning a Py_ssize_t.
Nothing good can come from having a hash table larger than the range of a hash value. Tests may pass but performance would degrade catastrophically.
loewis commentedon Sep 5, 2010
Correct. So it either needs to happen before 3.2, or wait until 4.0,
or the introduction of "wide" hashes needs to be done in a compatible
manner, likely requiring two parallel hashing infrastructures.
[-]Make hash values the same width as a pointer (or Py_ssize_t)[/-][+]Make hash values the same width as a pointer (or Py_ssize_t)[/+]pitrou commentedon Sep 5, 2010
Shouldn't there be a provision for ABI versioning?
Or do you suggest bumping to the next major number (4.0, 5.0...) be done on the basis of ABI changes?
loewis commentedon Sep 5, 2010
Am 05.09.2010 13:12, schrieb Antoine Pitrou:
There is certainly support for ABI versioning; the ABI version defined
in the PEP is called "python3.dll".
No, vice versa. The PEP promises that the ABI won't change until Python
4. For any change that might break the ABI, either a
backwards-compatible solution needs to be found, or the change be
deferred to Python 4.
[-]Make hash values the same width as a pointer (or Py_ssize_t)[/-][+]Make hash values the same width as a pointer (or Py_ssize_t)[/+]birkenfeld commentedon Sep 5, 2010
I would suggest making this change before the ABI freeze starts, then.
mdickinson commentedon Sep 6, 2010
Yes, please! (Provided this change can go in before 3.2.) For the numeric types at least, this should be a straightforward adjustment.
And while we're at it, we could clean up some of the undefined behaviour from integer overflow that's in the current hash functions (tuple.__hash__, for example).
birkenfeld commentedon Oct 15, 2010
Ping?
smontanaro commentedon Oct 15, 2010
Not that anybody needs my input on this, but...
Given the range of people advocating for this change, this looks to me
like it should be a release blocker for 3.2. Raymond's comment about
performance seems especially important, and since the world seems to
be moving toward 64-bit operating systems (certainly should happen in
a big way during the lifetime of Python 3) it seems worthwhile to hold
up further 3.2 releases until this is solved.
pitrou commentedon Oct 15, 2010
I think this is a bit exagerated. The performance issues will only
appear if you have huge dicts and sets.
The issue Raymond raised is the potential impossibility of making the
change /after/ we settle on a stable ABI. The question is whether the
ABI will be enforced starting from 3.2, or from a later date.
31 remaining items
mdickinson commentedon Oct 19, 2010
Yes, exactly.
I like (2); the use of Py_hash_t suggests to me that the type used for the hash is configurable independently of Py_ssize_t, which isn't true.
Also, with Py_hash_t it's no longer clear that printing a hash value (e.g., using PyErr_Format and friends) should use the '%zd' modifier.
casevh commentedon Oct 21, 2010
I've attached a patch that fixes hashing for numerical types, sys.hash_info is now correct, fixes typeobject.c/wrap_hashfunc and tupleobject.c/tuplehash to use Py_ssize_t instead of long, and uses Py_ssize_t instead of Py_hash_t.
I think it is clearer to use Py_ssize_t instead of Py_hash_t. I found two occurances where PyLong_FromLong needed to be replaced by PyLong_FromSsize_t and I think bugs like that would be easier to catch if Py_ssize_t is used.
casevh commentedon Oct 23, 2010
I maintain gmpy and it needs to calculate hash values for integers, floats, and rationals. I converted my hash calculations to use Py_ssize_t in a 64-bit Windows enviroment. All my tests pass when I build Python with my previous patch.
In hindsight, I think I made a mistake in my previous patch by eliminating Py_hash_t and using Py_ssize_t/size_t. I ended up defining Py_hash_t and Py_uhash_t in gmpy to simplify the code and to easily support older versions of Python.
I will work on a patch that defines Py_hash_t and Py_uhash_t and upload it later this evening.
casevh commentedon Oct 23, 2010
I've uploaded a patch against the current svn trunk that:
benjaminp commentedon Oct 23, 2010
Thank you. Applied in r85803.
pitrou commentedon Oct 23, 2010
Case's patch fixes test_builtin and test_complex failures on Windows 7 64-bit. But there's still a failure in test_dictviews:
======================================================================
FAIL: test_items_set_operations (test.test_dictviews.DictSetTest)
----------------------------------------------------------------------
Which boils down to the following issue:
There are also a bunch of possibly related failures in test_weakset:
======================================================================
FAIL: test_inplace_on_self (test.test_weakset.TestWeakSet)
----------------------------------------------------------------------
======================================================================
FAIL: test_or (test.test_weakset.TestWeakSet)
----------------------------------------------------------------------
======================================================================
FAIL: test_symmetric_difference (test.test_weakset.TestWeakSet)
----------------------------------------------------------------------
======================================================================
FAIL: test_union (test.test_weakset.TestWeakSet)
----------------------------------------------------------------------
======================================================================
FAIL: test_xor (test.test_weakset.TestWeakSet)
----------------------------------------------------------------------
Another bunch of test_pyclbr failures:
======================================================================
FAIL: test_decorators (test.test_pyclbr.PyclbrTest)
----------------------------------------------------------------------
======================================================================
FAIL: test_easy (test.test_pyclbr.PyclbrTest)
----------------------------------------------------------------------
======================================================================
FAIL: test_others (test.test_pyclbr.PyclbrTest)
----------------------------------------------------------------------
And a test_sys failure which is probably easy to fix:
File "Z:\svn\lib\test\test_sys.py", line 831, in test_objecttypes
check(s, basicsize)
File "Z:\svn\lib\test\test_sys.py", line 601, in check_sizeof
self.assertEqual(result, size, msg)
AssertionError: wrong size for <class 'str'>: got 74, expected 66
All these tests pass in 32-bit mode.
Case, you can run the regression test suite with:
python.exe -m test.regrtest
and invidual tests with e.g.:
python.exe -m test.regrtest -v test_dictviews
pitrou commentedon Oct 23, 2010
This patch seems to fix all aforementioned failures.
loewis commentedon Oct 23, 2010
These changes also look all reasonable to me.
pitrou commentedon Oct 23, 2010
Ok, I've committed them in r85808.
casevh commentedon Oct 23, 2010
On Win64, I get two unexpected failures:
I terminated test_capi after a Windows exception box popped up.
The dictviews test passes successfully.
pitrou commentedon Oct 23, 2010
The test_capi problem is not 64-bit-specific (see bpo-9116).
As for test_concurrent_futures, I also have a failure (not the same one) in both 32-bit and 64-bit builds here. I'm gonna open a separate issue.
loewis commentedon Oct 23, 2010
I recommend to declare this issue closed, and keep it closed unless somebody wants to propose to revert the change (widening the hash type) completely. Any remaining issues that people want to attribute to this change (correctly or incorrectly) should be reported as separate issues.