对于超过 64 个字符的字符串,什么会影响 Python 字符串比较性能?

2024-03-01

我正在尝试评估比较两个字符串是否会随着长度的增加而变慢。我的计算表明比较字符串应该花费摊销常数时间,但我的 Python 实验产生了奇怪的结果:

这是字符串长度(1 到 400)与时间(以毫秒为单位)的关系图。自动垃圾收集已禁用,并且gc.collect在每次迭代之间运行。

我每次比较 100 万个随机字符串,按如下方式计算匹配项。在取所有测量时间的最小值之前,该过程会重复 50 次。

for index in range(COUNT):
    if v1[index] == v2[index]:
        matches += 1
    else:
        non_matches += 1

长度 64 附近突然增加的原因可能是什么?

Note:以下代码片段可用于尝试重现问题,假设v1 and v2是两个长度随机字符串的列表nCOUNT 是它们的长度。

timeit.timeit("for i in range(COUNT): v1[i] == v2[i]",
  "from __main__ import COUNT, v1, v2", number=50)

进一步说明:我做了两个额外的测试:将字符串与is代替==完全抑制了该问题,性能对比约为210ms/1M。 由于已经提到了实习,我确保在每个字符串后面添加一个空格,这应该可以防止实习;这不会改变任何事情。那除了实习还有别的事吗?


Python can“实习生”短字符串;将它们存储在特殊的缓存中,并重新使用该缓存中的字符串对象。

然后比较字符串时,它首先测试它是否是相同的指针(例如内部字符串):

if (a == b) {
    switch (op) {
    case Py_EQ:case Py_LE:case Py_GE:
        result = Py_True;
        goto out;
// ...

仅当指针比较失败时,它才会使用大小检查并memcmp比较字符串。

驻留通常仅针对标识符(函数名称、参数、属性等)进行,但不适用于运行时创建的字符串值。

另一个可能的罪魁祸首是字符串常量;代码中使用的字符串文字在编译时存储为常量并在整个过程中重复使用;同样,只创建一个对象,并且对这些对象的身份测试速度更快。

对于不相同的字符串对象,Python 会测试长度是否相等、第一个字符是否相等,然后使用memcmp()内部 C 字符串上的函数。如果你的字符串是not被拘留或以其他方式重复使用相同的对象,所有其他速度特性都归结为memcmp()功能。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

对于超过 64 个字符的字符串,什么会影响 Python 字符串比较性能? 的相关文章

随机推荐