0

0

为什么Python要使用有明显缺陷的引用计数而不是像JavaScript一样的标记清除?

php中文网

php中文网

发布时间:2016-06-06 16:23:19

|

1933人浏览过

|

来源于php中文网

原创

引用计数有循环计数这个明显缺陷,那为什么Python还要使用引用计数而不是标记清除呢?

Bika.ai
Bika.ai

打造您的AI智能体员工团队

下载

回复内容:

引用计数最大的好处是回收及时:一个对象的引用计数归零的那一刻即是它成为垃圾的那一刻,同时也是它被回收的那一刻。而这正式 mark-sweep 等 tracing GC 算法的劣势:一个对象成为垃圾之后,直到被下一轮 GC 清理掉之前,还要在内存中留存一段时间(floating garbage)。

Python 的 GC 设计是,对于内部不包含指向其他对象的引用的对象(如字符串、数值类型等),采用引用计数,因为这些对象根本不可能产生循环引用。对于 List、Map 等可能产生循环引用的对象,则采用 mark-sweep。所以我的理解是,Python 的 GC 设计一定程度上综合了两类 GC 算法的优点——即保证回收的完整性,又力求回收的及时性。

Update

上文描述有偏颇,把评论里 R 大的补充贴上来:
对List啊Map啊Set之类的引用计数也在起作用的。mark-sweep只是备份。整套引用计数机制嵌在ceval.c里了,所有对象都要被它折腾到。换句话说不是List不被引用计数,而是List的引用计数如果自然降到零的话就自然按照引用计数机制释放;否则当cycle GC启动的时候就会对它处理。
不过通过引用计数来提高回收及时性这点仍然还是成立的。 这是一种设计取舍。用CPython的大家高兴就好呗。
其它Python实现有许多不用引用计数的,不高兴可以用它们(逃

另外CPython的引用计数是有mark-sweep备份的,不怕循环引用。
官网解释了这个选择(但其实也没说什么…):docs.python.org/2/faq/d
The details of Python memory management depend on the implementation. The standard C implementation of Python uses reference counting to detect inaccessible objects, and another mechanism to collect reference cycles, periodically executing a cycle detection algorithm which looks for inaccessible cycles and deletes the objects involved. The gc module provides functions to perform a garbage collection, obtain debugging statistics, and tune the collector’s parameters.

In the absence of circularities and tracebacks, Python programs do not need to manage memory explicitly.

Why doesn’t Python use a more traditional garbage collection scheme? For one thing, this is not a C standard feature and hence it’s not portable. (Yes, we know about the Boehm GC library. It has bits of assembler code for most common platforms, not for all of them, and although it is mostly transparent, it isn’t completely transparent; patches are required to get Python to work with it.)
...
Traditional GC also becomes a problem when Python is embedded into other applications. While in a standalone Python it’s fine to replace the standard malloc() and free() with versions provided by the GC library, an application embedding Python may want to have its own substitute for malloc() and free(), and may not want Python’s. Right now, Python works with anything that implements malloc() and free() properly.

然后请看这篇文章介绍较新的Python的“mark-swep GC”其实还是“分代式”的:patshaughnessy.net/2013

然后就是JavaScript也不一定是用mark-sweep的…语言规范没这么规定,实际实现也不全是用mark-sweep。 Python现在还用引用计数是因为很久很久以前Python很老土的在引用计数上打了个补丁,就这么一直打补丁打过来的

Garbage Collection for Python 先简单正面回答下题主,为啥python要用呢,因为作者愿意

如果题主是想问,改用“更好”的标记清除是不是一个更好的选择,那就可以多说一些了

首先,这个前提并不成立,学术一点的观点可以看《垃圾回收》这书,里面用“没有银弹”来形容算法的选择,即没有谁比谁好,只有在具体的场景下谁比谁适合的问题
引用计数最大好处是实时性,其次是在没有循环引用的情况下避免过多的over-allocation,内存不会浪费
这个实时性的重要性有多大呢,我猜在某些场景下,比大多数人认为的都重要很多,具体可以看我的blog文章,这篇也正好是在说其它会stop world的gc算法的缺点时候写的:
雪崩效应 - xtlisk的专栏
(文章是一个系列,对语言理论有兴趣的可以多交流:)
再者,循环引用真的是一个很大的缺陷吗,这个其实一直有争论,有人用统计来证明绝大多数代码和对象并不产生循环引用,用代码来规避即可,但也有人说在特定场景下会非常多(比如游戏中角色、装备、buff之间的关系),一般认为还是一个很大缺陷的,但并非不能解决

其次,问为什么之前先看是不是,py标准版的确主要用引用计数,但是其他实现并非这样,如Jython就直接依赖所在jvm的了。而且标准版并没有无视循环引用这个缺陷,在2.5就引入了gc模块,针对循环引用用局部标记清扫,注意是局部标记清扫而非普通的标记清扫,这个思想虽然一样但还是有特殊点,具体可以看《垃圾回收》这本书

事实上py用ref count是有一个缺陷的,一定程度甚至是很大程度上导致GIL这种机制,吐槽GIL的人非常多,但很少注意到跟GC的选择有关 Python刚刚被写出来的时候标记清除并没有今天这么大行其道, Java也是从引用计数走过来的。 ObjectiveC还在使用引用计数。

大部分策略总归有两面性, 比如你也要看看引用计数的好处啊:
  • 如果程序员能够做到不循环引用,那效率还是很高,不会带来VM停机啊
  • 再一个来说为什么用引用计数?简单啊, 你听完马上自己就可以去写一个。 易懂啊,几分钟就能说明白了。 可以对比标记清除
等到Python长到足够大开始像Java一样担忧引用计数的时候,悲剧发生了,好像怎么都改不过来了。 相信到今天还是有不少人在致力于去掉Python里的引用计数

巴拉巴拉的絮絮叨叨
Python memory management compared with other language runtime 你调试Java程序时在暂挂态触发一个JVM GC看看,不感觉卡一下吗? 为什么JavaScript要使用有明显缺陷的标记清除而不是像Python一样的引用计数? 为什么JavaScript要使用有明显缺陷的标记清除而不是像Python一样的引用计数?
标记清除有性能低下这个明显缺陷,那为什么JavaScript还要使用标记清除而不是引用计数呢? 引用计数比较方便让第三方拓展模块参与管理cpython的内存。第三方的拓展模块可以容易的保存cpython的指针而不必担心这个指针所指向的内存被释放了。

相关文章

python速学教程(入门到精通)
python速学教程(入门到精通)

python怎么学习?python怎么入门?python在哪学?python怎么学才快?不用担心,这里为大家提供了python速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
excel制作动态图表教程
excel制作动态图表教程

本专题整合了excel制作动态图表相关教程,阅读专题下面的文章了解更多详细教程。

20

2025.12.29

freeok看剧入口合集
freeok看剧入口合集

本专题整合了freeok看剧入口网址,阅读下面的文章了解更多网址。

65

2025.12.29

俄罗斯搜索引擎Yandex最新官方入口网址
俄罗斯搜索引擎Yandex最新官方入口网址

Yandex官方入口网址是https://yandex.com;用户可通过网页端直连或移动端浏览器直接访问,无需登录即可使用搜索、图片、新闻、地图等全部基础功能,并支持多语种检索与静态资源精准筛选。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

197

2025.12.29

python中def的用法大全
python中def的用法大全

def关键字用于在Python中定义函数。其基本语法包括函数名、参数列表、文档字符串和返回值。使用def可以定义无参数、单参数、多参数、默认参数和可变参数的函数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

16

2025.12.29

python改成中文版教程大全
python改成中文版教程大全

Python界面可通过以下方法改为中文版:修改系统语言环境:更改系统语言为“中文(简体)”。使用 IDE 修改:在 PyCharm 等 IDE 中更改语言设置为“中文”。使用 IDLE 修改:在 IDLE 中修改语言为“Chinese”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

16

2025.12.29

C++的Top K问题怎么解决
C++的Top K问题怎么解决

TopK问题可通过优先队列、partial_sort和nth_element解决:优先队列维护大小为K的堆,适合流式数据;partial_sort对前K个元素排序,适用于需有序结果且K较小的场景;nth_element基于快速选择,平均时间复杂度O(n),效率最高但不保证前K内部有序。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

12

2025.12.29

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

134

2025.12.29

抖音网页版入口在哪(最新版)
抖音网页版入口在哪(最新版)

抖音网页版可通过官网https://www.douyin.com进入,打开浏览器输入网址后,可选择扫码或账号登录,登录后同步移动端数据,未登录仅可浏览部分推荐内容。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

63

2025.12.29

快手直播回放在哪看教程
快手直播回放在哪看教程

快手直播回放需主播开启功能才可观看,主要通过三种路径查看:一是从“我”主页进入“关注”标签再进主播主页的“直播”分类;二是通过“历史记录”中的“直播”标签页找回;三是进入“个人信息查阅与下载”里的“直播回放”选项。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

18

2025.12.29

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 0.6万人学习

Django 教程
Django 教程

共28课时 | 2.6万人学习

SciPy 教程
SciPy 教程

共10课时 | 0.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号