CPython的静态对象地址和碎片

2024-04-19

I read

对于Python来说,if(x)是存储x的内存地址。

这是给定的id对象的属性永远不会改变,这意味着对象在其生命周期中始终存储在给定的内存地址中。这就引出了一个问题:(虚拟)内存碎片怎么样?

说一个物体A位于地址 1(有id1),占用10个字节,所以占用地址1-10。目的B has id11 占用字节11-12,对象C占用地址13-22。一旦 B 超出范围并被 GC 回收,我们就会产生碎片。

这个难题如何解决?


CPython 对小对象使用自己的内存分配器,pymalloc 分配器 https://docs.python.org/3/c-api/memory.html#the-pymalloc-allocator。可以在以下位置找到非常好的描述代码本身 https://github.com/python/cpython/blob/8905fcc85a6fc3ac394bc89b0bbf40897e9497a6/Objects/obmalloc.c#L741.

这个分配器非常擅长避免内存碎片,因为它有效地重用了释放的内存。然而,这只是一种启发式方法,人们可能会想出导致内存碎片的场景。

让我们看看当我们分配一个大小为 1 字节的对象时会发生什么。

CPython 对于小于 512 字节的对象有自己的所谓的 arena。显然,1 字节请求将由其分配器管理。

请求的大小分为 64 个不同的类别:第 0 类适用于 1..8 字节的大小,第 1 类适用于 9..16 字节的大小,依此类推 - 这是由于需要 8 字节对齐。上述每个类都有自己或多或少的独立/专用内存。我们的要求是 0 级。

我们假设这是对此尺寸级别的第一个请求。将创建一个新的“池”或重新使用一个空池。一个游泳池是4KB big https://github.com/python/cpython/blob/8905fcc85a6fc3ac394bc89b0bbf40897e9497a6/Objects/obmalloc.c#L867,因此有 512 个 8 字节“块”的空间。尽管只请求 1 个字节,但我们将阻塞占用块的另外 7 个字节,因此它们不能用于其他对象。所有空闲块都保存在一个列表中 - 一开始所有 512 个块都在此列表中。分配器从该空闲块列表中删除第一个块,并将其地址作为指针返回。

该池本身被标记为“已使用”,并添加到 0 级已用池列表中。

现在,分配另一个大小

删除第一个对象很容易 - 我们将占用的块添加为(到目前为止单个)已使用池中的空闲块列表的头部。

当创建 8 字节的新对象时,将使用空闲块列表中的第一个块,这是第一个现已删除的对象使用的块。

正如您所看到的,内存被重用,因此内存碎片大大减少。这并不意味着不能存在内存碎片:

分配 512 个 1 字节对象后,第一个池将变“满”,并且将创建/使用第 0 类大小的新池。一旦我们添加了另外 512 个对象,第二个池也将变得“满”。等等。

现在,如果删除前 511 个元素 - 仍然会有一个字节阻塞整个 4KB,无法用于other类。

仅当最后一个块被释放时,池才变为“空”,从而可以重新用于其他大小类别。


空池不会返回给操作系统,而是留在竞技场中并被重用。然而,pymalloc管理多个竞技场 https://github.com/python/cpython/blob/8905fcc85a6fc3ac394bc89b0bbf40897e9497a6/Objects/obmalloc.c#L1074,如果一个 arena 变得“未使用”,它可能会被释放,并将占用的内存(即池)返回给操作系统。

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

CPython的静态对象地址和碎片 的相关文章

随机推荐

  • 使用python统计lmdb数据库中的记录数

    我打开一个lmdb使用此代码的数据库 lmdb env lmdb open source path readonly True 如何计算该数据库中的记录数 我认为应该是这样的 lmdb env lmdb open lmdb file nam
  • 检测默认网络浏览器的代理设置

    MSDN样本 HttpWebRequest myWebRequest HttpWebRequest WebRequest Create http www microsoft com WebProxy myProxy new WebProxy
  • JSON 的 XSLT 等效项

    有没有一个XSLT http www w3 org TR xslt相当于 JSON 允许我对 JSON 进行转换 就像 XSLT 对 XML 所做的那样 JSON 的 XSLT 等效项 候选列表 工具和规范 Tools 1 XSLT htt
  • SceneBuilder 不会加载通过 FXML 引用另一个自定义控件的自定义控件

    我创建了一个基于 FXML 的自定义控件 该控件又引用另一个基于 FXML 的自定义控件 当我在 Eclipse 中加载它们时 它们都工作得很好 但是当我尝试将它们导入到 SceneBuilder 中时 外部控件 包含另一个控件的一个 无法
  • PHP 中短代码的正则表达式模式

    我编写的用于匹配 PHP 中的短代码的正则表达式有问题 这是模式 其中 shortcode是短代码的名称 shortcode shortcode 现在 这个正则表达式对于这些格式表现得非常好 shortcode shortcode valu
  • 为什么不能在 svg 路径元素上使用transform:translateZ?

    我想对内联 svg 元素的部分进行动画处理 我认为你可以在 svg 路径元素上使用 css 转换 从而为 svg 的部分设置动画 这真的很酷 但在使用它之后 我遇到了 translateZ 函数的问题 由于某种原因 在路径元素上使用第三维似
  • 如何删除材料设计按钮中的额外填充或边距?

    我正在尝试创建一个附加到按钮上方的 TextView 的按钮 如下图所示 上面的截图取自Note 4 操作系统版本为5 0 1 下面是用于实现UI的代码 布局 xyz xml
  • C++ 编码指南 102

    如果您被允许在 101 条准则中添加另一个编码准 则 C 编码标准 Herb Sutter 和 Andrei Alexandrescu http www gotw ca publications c cs htm 您会添加哪一个 一年后再写
  • 模板什么时候结束?

    模板什么时候结束 我们来看看这段代码 template
  • 带有 vararg observables 的 RxJava zip

    当我们确切地知道有多少个具有确切类型的可观察量并且我们想要压缩时 我们会这样做 Observable
  • JetBrains IDE 启动时出错:应用程序无法正确启动 (0xc000007b)

    我遇到了这个错误 但在重新安装 IDE 两次后几乎找不到解决方案 甚至我安装了 多合一运行时 但这也无济于事 因为我认为问题最初是在我更改了 Windows Defender 设置中的一些设置后开始的然后尝试重置它们 但肯定其他人报告了这个
  • lambda:通过引用捕获 const 引用是否应该产生未定义的行为?

    我刚刚在代码中发现了一个令人讨厌的错误 因为我通过引用捕获了对字符串的 const 引用 当 lambda 运行时 原始字符串对象已经消失了 引用的值是空的 而目的是它包含原始字符串的值 因此出现了错误 让我困惑的是 这并没有在运行时引发崩
  • BigInteger 数字的实现和性能

    我用 C 编写了一个 BigInteger 类 它应该能够对任何大小的所有数字进行运算 目前 我正在尝试通过比较现有算法并测试它们最适合哪些位数来实现非常快速的乘法方法 但我遇到了非常意外的结果 我尝试进行 20 次 500 位数字的乘法
  • Inflector.Net 的替代品

    我想在我的项目中使用 inflector net 刚刚谷歌了一下 好像已经消失了 http andrewpeters net inflectornet http andrewpeters net inflectornet 还有其他选择吗 编
  • Chrome 开发工具中的 __puppeteer_evaluation_script__ 为空

    Puppeteer 版本 9 0 0 将调试器放入 JavaScript 代码并启动 puppeteer 时 chrome 开发工具中的源代码为空 使用 Node 运行脚本 scripts test echo Error no test s
  • Docker 和 Python virtualenv 有什么区别?

    根据我对Docker的理解 它是一个用于虚拟环境的工具 用他们的行话来说 这称为 容器化 这或多或少就是 Python 的 virtualenv 所做的事情 但是 您可以使用 virtualenvin码头工人 那么 它是虚拟环境中的虚拟环境
  • 如何监控 Tomcat 服务器上的多个 Web 应用程序(使用 JMX)?

    有没有办法监控单个 Web 应用程序的 CPU 和内存消耗Tomcat server I have Tomcat打开其 JVM 下的所有 Web 应用程序 因此我只能看到一个 JVM 无法单独监控每个 Web 应用程序 Web 应用程序是密
  • jquery中删除多个元素

    在我当前的代码中我有这样的 foo remove bar remove 有没有办法通过使用删除多个元素remove once 它不限于 remove 但只需用逗号分隔选择器 foo bar remove 多重选择器 选择器1 选择器2 选择
  • 如何调整 UIImageView 的大小以适应底层图像而不移动它?

    我有一个 UIImageView 其框架在加载图像之前设置 对于图像来说总是太大 因此 例如 当我尝试圆角时 什么也没有发生 如何调整框架大小 使其与底层图像的大小相同 同时确保 UIImageView 的中心点不会改变 如果更改 UIVi
  • CPython的静态对象地址和碎片

    I read 对于Python来说 if x 是存储x的内存地址 这是给定的id对象的属性永远不会改变 这意味着对象在其生命周期中始终存储在给定的内存地址中 这就引出了一个问题 虚拟 内存碎片怎么样 说一个物体A位于地址 1 有id1 占用