diff options
author | INADA Naoki <songofacandy@gmail.com> | 2016-12-07 09:34:44 (GMT) |
---|---|---|
committer | INADA Naoki <songofacandy@gmail.com> | 2016-12-07 09:34:44 (GMT) |
commit | 2c5a830f2ac654e643eaa29ef60bd51977700376 (patch) | |
tree | 9a55e633b6c846cb22e173ee44d0c818c4fe710b /Objects/dictobject.c | |
parent | 0c78634d785361dcde0c2c138e8bf5f9bb744d3d (diff) | |
download | cpython-2c5a830f2ac654e643eaa29ef60bd51977700376.zip cpython-2c5a830f2ac654e643eaa29ef60bd51977700376.tar.gz cpython-2c5a830f2ac654e643eaa29ef60bd51977700376.tar.bz2 |
Issue #28731: Optimize _PyDict_NewPresized() to create correct size dict.
Improve speed of dict literal with constant keys up to 30%.
Diffstat (limited to 'Objects/dictobject.c')
-rw-r--r-- | Objects/dictobject.c | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/Objects/dictobject.c b/Objects/dictobject.c index d8ab91f..97f0418 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -388,7 +388,7 @@ dk_set_index(PyDictKeysObject *keys, Py_ssize_t i, Py_ssize_t ix) * This can be used to reserve enough size to insert n entries without * resizing. */ -#define ESTIMATE_SIZE(n) (((n)*3) >> 1) +#define ESTIMATE_SIZE(n) (((n)*3+1) >> 1) /* Alternative fraction that is otherwise close enough to 2n/3 to make * little difference. 8 * 2/3 == 8 * 5/8 == 5. 16 * 2/3 == 16 * 5/8 == 10. @@ -1357,12 +1357,26 @@ make_keys_shared(PyObject *op) PyObject * _PyDict_NewPresized(Py_ssize_t minused) { + const Py_ssize_t max_presize = 128 * 1024; Py_ssize_t newsize; PyDictKeysObject *new_keys; - for (newsize = PyDict_MINSIZE; - newsize <= minused && newsize > 0; - newsize <<= 1) - ; + + /* There are no strict guarantee that returned dict can contain minused + * items without resize. So we create medium size dict instead of very + * large dict or MemoryError. + */ + if (minused > USABLE_FRACTION(max_presize)) { + newsize = max_presize; + } + else { + Py_ssize_t minsize = ESTIMATE_SIZE(minused); + newsize = PyDict_MINSIZE; + while (newsize < minsize) { + newsize <<= 1; + } + } + assert(IS_POWER_OF_2(newsize)); + new_keys = new_keys_object(newsize); if (new_keys == NULL) return NULL; |