CPython和PyPy如何决定何时调整集合的大小?

CPython和PyPy如何决定何时调整集合的大小?,python,set,cpython,pypy,python-internals,Python,Set,Cpython,Pypy,Python Internals,在向CPython和PyPy上的集合添加元素时,何时调整它们的大小,以及基础容器的大小如何 这个问题原则上类似于最大负载系数。CPython用于决定何时调整大小: if (!(so->used > n_used && so->fill*3 >= (so->mask+1)*2)) 这基本上意味着当2/3满时,容器将调整大小 调整大小本身会使大型集合的空间量增加一倍,小型集合的空间量增加四倍: return set_table_resize(so, s

在向CPython和PyPy上的集合添加元素时,何时调整它们的大小,以及基础容器的大小如何

这个问题原则上类似于最大负载系数。

CPython用于决定何时调整大小:

if (!(so->used > n_used && so->fill*3 >= (so->mask+1)*2))
这基本上意味着当2/3满时,容器将调整大小

调整大小本身会使大型集合的空间量增加一倍,小型集合的空间量增加四倍:

return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4);
Armin Rigo在评论中指出,PyPy使用字典实现其集合,因此:

这是CPython的输出:

Completion: [99%]
0      = 0b0                  [found %: 100%]
5      = 0b101                [found %: 83%]
21     = 0b10101              [found %: 12%]
85     = 0b1010101            [found %: 94%]
341    = 0b101010101          [found %: 97%]
1365   = 0b10101010101        [found %: 100%]
5461   = 0b1010101010101      [found %: 100%]
21845  = 0b101010101010101    [found %: 100%]
87381  = 0b10101010101010101  [found %: 100%]
您可以看到
10101。。。₂模式,这是从2除以3的幂得到的,此时对象将调整大小。(因为脚本是0索引的,所以在此之后它会调整一个大小)

在PyPy3上,将迭代次数更改为更大(
iterations=1000;internal\u iterations=100000
),我得到

这意味着PyPy的策略是相同的

奇怪的是,可能是由于JIT或GC,有时我会得到更像:

Completion: [100%]
0      = 0b0                  [found %: 13%]
5      = 0b101                [found %: 11%]
21     = 0b10101              [found %: 22%]
22     = 0b10110              [found %: 6%]
23     = 0b10111              [found %: 5%]
24     = 0b11000              [found %: 5%]
341    = 0b101010101          [found %: 30%]
1365   = 0b10101010101        [found %: 66%]
5461   = 0b1010101010101      [found %: 98%]

取决于迭代次数。我想这是由于围绕这一点的迭代次数相对较少,这可能并不意味着什么。如果GC收集发生在第20项附近,很容易造成这种压力。

这正是我最近看到的,我想我应该做一个快速的总结,这是一个很好的反复检查的方法。调整集合的大小从来没有在
setobject.py
中出现过。相反,它是在公共场所。集合只是带有RPython“void”值的字典。
Completion: [99%]
0      = 0b0                  [found %: 100%]
5      = 0b101                [found %: 83%]
21     = 0b10101              [found %: 12%]
85     = 0b1010101            [found %: 94%]
341    = 0b101010101          [found %: 97%]
1365   = 0b10101010101        [found %: 100%]
5461   = 0b1010101010101      [found %: 100%]
21845  = 0b101010101010101    [found %: 100%]
87381  = 0b10101010101010101  [found %: 100%]
Completion: [100%]
0      = 0b0                  [found %: 78%]
5      = 0b101                [found %: 6%]
21     = 0b10101              [found %: 5%]
341    = 0b101010101          [found %: 24%]
1365   = 0b10101010101        [found %: 66%]
5461   = 0b1010101010101      [found %: 100%]
21845  = 0b101010101010101    [found %: 100%]
87381  = 0b10101010101010101  [found %: 71%]
Completion: [100%]
0      = 0b0                  [found %: 13%]
5      = 0b101                [found %: 11%]
21     = 0b10101              [found %: 22%]
22     = 0b10110              [found %: 6%]
23     = 0b10111              [found %: 5%]
24     = 0b11000              [found %: 5%]
341    = 0b101010101          [found %: 30%]
1365   = 0b10101010101        [found %: 66%]
5461   = 0b1010101010101      [found %: 98%]