我发现我正在使用静态字符串非常频繁地和嵌套环中访问python dicts。我猜python需要为每个访问访问串起字符串,这可能会影响性能。
例如:
for d in large_list_of_dicts:
for d2 in d['trees']:
v = d2['leaves']
Cython Hash是否将这些静态的弦键(仅一次)重复使用这些哈希值?如果是这样,这可能会大大提高此类循环的性能?
cython在这里不会执行任何魔术:它只会将呼叫委派给PyDict_GetItemWithError
-基本上是Python解释器会做的相同的事情(但可能更快)。
但是,一个unicode-object(我假设我们在谈论python3-strings)缓存其哈希值(在 PyUnicodeObject.hash
-ember字段中),因此只需要一次计算一次 - 这是有道理的,因为unicode-object是不变的,这意味着哈希无法更改。
这是负责哈希计算/缓存的CPYTHON代码:
#define _PyUnicode_HASH(op)
(((PyASCIIObject *)(op))->hash)
...
static Py_hash_t
unicode_hash(PyObject *self)
{
...
// if hash already calculated, return cached value
if (_PyUnicode_HASH(self) != -1)
return _PyUnicode_HASH(self);
...
// else caclculate hash, cache value, return it
x = _Py_HashBytes(PyUnicode_DATA(self),
PyUnicode_GET_LENGTH(self) * PyUnicode_KIND(self));
_PyUnicode_HASH(self) = x;
return x;
}
您可以看到,Cython不需要避免使用哈希结果 - 这种优化已经由Cpython完成。
通过在此处使用Cython,最多可以获胜10-30%,因为它会消除该部分的解释器(例如,请参见此件如此之多) - 不是真的,但总比没有好。