代码之家  ›  专栏  ›  技术社区  ›  Mark Tolonen

sys.getrefcount()返回非常大的引用计数

  •  5
  • Mark Tolonen  · 技术社区  · 1 年前

    在CPython 3.11中,以下代码为一些对象返回了非常大的引用计数。它似乎遵循预缓存的对象,如整数-5到256,但CPython 3.10没有:

    Python 3.11.2 (tags/v3.11.2:878ead1, Feb  7 2023, 16:38:35) [MSC v.1934 64 bit (AMD64)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import sys
    >>> for i in (-6, -5, 0, 255, 256, 257):
    ...    print(i, sys.getrefcount(i))
    ...
    -6 5
    -5 1000000004
    0 1000000535
    255 1000000010
    256 1000000040
    257 5
    
    Python 3.10.8 (tags/v3.10.8:aaaf517, Oct 11 2022, 16:50:30) [MSC v.1933 64 bit (AMD64)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import sys
    >>> for i in (-6, -5, 0, 255, 256, 257):
    ...    print(i, sys.getrefcount(i))
    ...
    -6 5
    -5 6
    0 234
    255 8
    256 26
    257 5
    

    PEP 683 - Immortal Objects, Using a Fixed Refcount 可能有关联,但在中未提及 What's New in Python 3.11 ,也没有变化 sys.getrefcount() 记录在案。

    有人知道这一变化吗?

    1 回复  |  直到 1 年前
        1
  •  7
  •   user2357112    1 年前

    这是 与PEP 683相关,但一旦实施了PEP683,它很可能会被PEP683取代。

    此refcount更改首次引入于 commit 于2021年12月13日,引入了 _PyObject_IMMORTAL_INIT 宏:

    #define _PyObject_IMMORTAL_INIT(type) \
        { \
            .ob_refcnt = 999999999, \
            .ob_type = type, \
        }
    

    在此更改之前,小int引用计数被初始化为1。这一变化使得它们的refcount被初始化为999999999。

    相关问题的讨论是 here ,并且提交的pull请求是 here .

    999999999的值似乎是从Guido van Rossum在编写一个无关工具时做出的一个相当武断的决定中复制的。引用 message 由Guido在问题讨论中:

    我在deepfreeze.py中使用了999999999来表示“不朽的对象”。它有 被其他人复制(小整数本质上也是不朽的)。我 不太确定如果 解释器被反复完成和重新初始化。一旦我们有 官方不朽的对象(见PEP-683)我们应该切换到那个。

    推荐文章