热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

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

回复内容:

引用计数最大的好处是回收及时:一个对象的引用计数归零的那一刻即是它成为垃圾的那一刻,同时也是它被回收的那一刻。而这正式 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的指针而不必担心这个指针所指向的内存被释放了。
推荐阅读
  • 导读:在编程的世界里,语言纷繁多样,而大部分真正广泛流行的语言并不是那些学术界的产物,而是在通过自由发挥设计出来的。和那些 ... [详细]
  • 让你明白kvm是什么
    参考:https:blog.csdn.netbbwangjarticledetails80465320KVM工具集合:libvirt:操作和管理KVM虚机的虚拟化API ... [详细]
  • 闭包一直是Java社区中争论不断的话题,很多语言都支持闭包这个语言特性,闭包定义了一个依赖于外部环境的自由变量的函数,这个函数能够访问外部环境的变量。本文以JavaScript的一个闭包为例,介绍了闭包的定义和特性。 ... [详细]
  • 数学中的常见的距离公式
    数学中的常见的距离公式转载自:点击打开链接最近看到文章中对距离的衡量依据所针对的问题,针对所使用到的各种距离公式从网上搜罗如下1.欧氏距离,最常见的两点之间或多点之间的距离表示法, ... [详细]
  • 安装mysqlclient失败解决办法
    本文介绍了在MAC系统中,使用django使用mysql数据库报错的解决办法。通过源码安装mysqlclient或将mysql_config添加到系统环境变量中,可以解决安装mysqlclient失败的问题。同时,还介绍了查看mysql安装路径和使配置文件生效的方法。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 本文介绍了计算机网络的定义和通信流程,包括客户端编译文件、二进制转换、三层路由设备等。同时,还介绍了计算机网络中常用的关键词,如MAC地址和IP地址。 ... [详细]
  • 欢乐的票圈重构之旅——RecyclerView的头尾布局增加
    项目重构的Git地址:https:github.comrazerdpFriendCircletreemain-dev项目同步更新的文集:http:www.jianshu.comno ... [详细]
  • 云原生应用最佳开发实践之十二原则(12factor)
    目录简介一、基准代码二、依赖三、配置四、后端配置五、构建、发布、运行六、进程七、端口绑定八、并发九、易处理十、开发与线上环境等价十一、日志十二、进程管理当 ... [详细]
  • Allegro总结:1.防焊层(SolderMask):又称绿油层,PCB非布线层,用于制成丝网印板,将不需要焊接的地方涂上防焊剂.在防焊层上预留的焊盘大小要比实际的焊盘大一些,其差值一般 ... [详细]
  • 有关phpfgetss()函数的文章推荐10篇
    有关phpfgetss()函数的文章推荐10篇:了解如何使用PHP的各种文件函数。查看诸如fopen、fclose和feof之类的基本文件函数;了解诸如fgets、fgetss和f ... [详细]
  • php课程Json格式规范需要注意的小细节
    JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgramming ... [详细]
  • 1、概述首先和大家一起回顾一下Java消息服务,在我之前的博客《Java消息队列-JMS概述》中,我为大家分析了:然后在另一篇博客《Java消息队列-ActiveMq实战》中 ... [详细]
  • 前言对于从事技术的人员来说ajax是这好东西,都会使用,而且乐于使用。但对于新手,开发一个ajax实例,还有是难度的,必竟对于他们这是新东西。leo开发一个简单的ajax实例,用的是 ... [详细]
  • PHP编程能开发哪些应用?
    导读:很多朋友问到关于PHP编程能开发哪些应用的相关问题,本文编程笔记就来为大家做个详细解答,供大家参考,希望对大家有所帮助!一起来看看吧!本文目录一览: ... [详细]
author-avatar
wjw0000
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有