changeset: 90546:592a57682ced user: Raymond Hettinger date: Sat May 03 16:41:19 2014 -0700 files: Misc/NEWS Modules/_collectionsmodule.c description: Issue #21101: Eliminate double hashing in the C code for collections.Counter(). diff -r 39f475aa0163 -r 592a57682ced Misc/NEWS --- a/Misc/NEWS Sat May 03 16:32:11 2014 -0700 +++ b/Misc/NEWS Sat May 03 16:41:19 2014 -0700 @@ -73,6 +73,9 @@ Decimal.quantize() method in the Python version. It had never been present in the C version. +- Issue #21101: Eliminate double hashing in the C speed-up code for + collections.Counter(). + - Issue #21321: itertools.islice() now releases the reference to the source iterator when the slice is exhausted. Patch by Anton Afanasyev. diff -r 39f475aa0163 -r 592a57682ced Modules/_collectionsmodule.c --- a/Modules/_collectionsmodule.c Sat May 03 16:32:11 2014 -0700 +++ b/Modules/_collectionsmodule.c Sat May 03 16:41:19 2014 -0700 @@ -1831,18 +1831,29 @@ if (mapping_get != NULL && mapping_get == dict_get && mapping_setitem != NULL && mapping_setitem == dict_setitem) { while (1) { + Py_hash_t hash; + key = PyIter_Next(it); if (key == NULL) break; - oldval = PyDict_GetItem(mapping, key); + + if (!PyUnicode_CheckExact(key) || + (hash = ((PyASCIIObject *) key)->hash) == -1) + { + hash = PyObject_Hash(key); + if (hash == -1) + goto done; + } + + oldval = _PyDict_GetItem_KnownHash(mapping, key, hash); if (oldval == NULL) { - if (PyDict_SetItem(mapping, key, one) == -1) + if (_PyDict_SetItem_KnownHash(mapping, key, one, hash) == -1) break; } else { newval = PyNumber_Add(oldval, one); if (newval == NULL) break; - if (PyDict_SetItem(mapping, key, newval) == -1) + if (_PyDict_SetItem_KnownHash(mapping, key, newval, hash) == -1) break; Py_CLEAR(newval); }