【问题标题】:Which elementary objects are cached by Python [closed]Python缓存了哪些基本对象[关闭]
【发布时间】:2021-08-25 11:36:58
【问题描述】:

众所周知,Python(或至少是 CPython)缓存了一些第一个整数。也就是说,以下成立

a = 1
b = 1
print(a is b)  # True 

同时

a = 1000
b = 1000
print(a is b)  # False

更广泛地说,我们可以使用下面列出的方法来查看缓存了哪些基本对象(或者“是单例”,如果您愿意的话)。

def does_survive_pickling(obj):
    after_pickling = pkl.loads(pkl.dumps(obj))
    return obj is after_pickling

我的问题是

  • 表现出这种行为的对象是什么? (比如说,“存活”酸洗方法)

    • 在我的 CPython 3.9.1 中,它们至少是 [-5, 256] 中的整数(对应的字符也是如此,即 8 位 ACII)、()NoneTrueFalse 和 @ 987654328@。还有其他人吗?
  • 这些对象的数量和种类取决于什么条件?

    • 我认为 Python 的实现非常重要。

    • 还有什么(比如,对于 CPython)?版本?硬件(例如 32 位与 64 位处理器)?还有其他的吗?

  • 是否有可能在某处找到这些信息? (在文档中?)

如果有任何 cmets、答案或有用的链接,我会很高兴。谢谢!

也许 CPython 的行为对我来说是唯一真正重要的。但是,出于好奇,欢迎提供有关 PyPy 和其他内容的信息。


作为背景,我正在开发一个需要管理其内存资源的库。因此,我努力学习更多关于 Python 内存管理的知识。在这种情况下,我对 pickled-unpickled 对象(更普遍地是序列化-反序列化)的内存占用感兴趣。

比如说,你从一堆内部结构相互交织的对象开始。如果将这些对象中的每一个都保存到磁盘并再次加载,会发生什么(内存消耗增加了多少)?

如果是一些1的嵌套列表,与1000的相同列表有很大的不同。

【问题讨论】:

  • “是否有可能在某处找到这些信息?” - 是的,在源代码中,因为这些只是实现细节。您问题的第二部分非常广泛,并且本身就是一个不同的问题,这使得您的整个问题对于 SO...
  • @ThierryLathuille 我知道这可能是一个深深隐藏的小实现细节。不过,我不确定。如果它真的是一个非常不稳定的功能,我将不再使用它。但也许(再次,我不知道,这就是我要问的原因)它在 Python 版本(甚至可能是实现)之间更普遍的行为相当稳定。在这种情况下,了解这一点很有用。 ... 例如iter 用于dict 的插入顺序曾经是CPython 的实现细节,现在它是必需的功能(但是,请理解这里的细节级别完全不同)。
  • 插入顺序的保留是仅在一个 CPython 版本中的实现细节,紧接在其升级为语言功能之前。我相信它当时也是这样宣布的:它是有意提前推出一个版本作为测试用例的。

标签: python memory-management python-internals


【解决方案1】:

依赖实施细节是未来灾难的秘诀......

对象缓存是一个实现细节,实际缓存的对象可能会在任何新的 Python 版本中更改,而不会发出任何警告。

如果你有很多大的只读对象,其中大部分是相等的,那么你应该考虑在pickle模块级别实现特殊处理,例如特殊的__reduce__方法,对__getstate____setstate__,或使用带外数据处理。不幸的是,很难知道哪种方法最适合您的实际用例。我的意见是,您应该深入研究pickle 模块文档,以了解是否可以使用记录的方式来节省内存。

【讨论】:

  • 我同意某种“硬依赖”(如果它改变,程序中断)在这种情况下确实是一个问题。但是,我的意思是仅用于更准确的估计,而只是估计。因此,实现上或多或少的细微差别不会成为问题。感谢您对泡菜特殊方法的提示!
猜你喜欢
  • 2012-05-27
  • 1970-01-01
  • 2011-02-14
  • 2019-04-01
  • 2013-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-12
相关资源
最近更新 更多