Python垃圾回收及Linux Fork

目录
  • 1.Linux fork简介
  • 1.Copy-On-Write策略增加Python多进程内存占用的原因
  • 3.解决办法

前言:

在口袋助理看到了其他部门的同事针对Python2内存占用做的一点优化工作,自己比较感兴趣,遂记录下。

1.Linux fork简介

fork是Linux提供的创建子进程的系统调用。为了优化创建进程速度,Linux内核使用了Copy-on-Write的方式去创建进程,所谓Copy-on-Write是指执行fork之后,
内核并不立即给子进程分配物理内存空间,而是让子进程的虚内存映射到父进程的物理内存。仅仅当子进程向地址空间中执行写入操作时,才给它分配一段物理内存。
通过这种方式既优化了进程创建的时间,又减少了子进程的内存占用。

1.Copy-On-Write策略增加Python多进程内存占用的原因

Python GC采用引用技术的方式去管理对每个对象的引用,每一个被GC跟踪的对象会由一个PyGC_Head的结构体去表示。如下所示,其中gc_refs就是每个对象的引用计数值,
当我们在子进程中读取父进程创建的对象的时候,就会导致子进程的虚地址空间中的gc_refs加1,从而触发了内核的缺页中断,这是内核就会给子进程创建新的物理内存。
仅仅是简单的读取操作就会导致新的内存空间产生。

/* GC information is stored BEFORE the object structure. */
typedef union _gc_head 
{
    struct {
        union _gc_head *gc_next;
        union _gc_head *gc_prev;
        Py_ssize_t gc_refs;
    } gc;
    long double dummy; /* force worst-case alignment */
} PyGC_Head;

3.解决办法

python3的解决方法:

针对这个问题,Python3.7增加了三组API(有instagram团体提交的)[1]。

freeze用于将GC追踪的所有对象都移动到永生代(permanent generation),之后垃圾回收会忽略这些被设置为永生代的对象。

实际使用中,我们可以在父进程中执行freeze函数,然后子进程中使用和父进程共享的对象,这样对象的引用技术就不会增加,从而避免了COW的发生。

python2的解决方法:

  • (1) 针对Python2,我们可以简单的把Python3的相关函数移植过来
  • (2) 使用multiprocessing.Array去共享数据。Array会从共享内存中取一段取存储数据,并不会增加引用技术值,从而触发COW。

实现方面,Array使用Posix共享内存 + mmap去实现。[3]

#!/usr/bin/env python
# coding=utf-8
from multiprocessing import Array
import os
import sys

def foo():
    shared_cache = Array('i', range(0, 100), lock=False)
    pid = os.fork()
    if pid > 0:
        print("parent:", sys.getrefcount(shared_cache)) 
    elif pid == 0:
        print("child:", sys.getrefcount(shared_cache))

foo()

到此这篇关于Python垃圾回收及Linux Fork的文章就介绍到这了,更多相关Python垃圾回收及Linux Fork内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

参考:

1.https://instagram-engineering.com/copy-on-write-friendly-python-garbage-collection-ad6ed5233ddf
2.https://llvllatrix.wordpress.com/2016/02/19/python-vs-copy-on-write/
3.https://github.com/python/cpython/blob/main/Lib/multiprocessing/shared_memory.py

(0)

相关推荐

  • 分析python垃圾回收机制原理

    目录 引用计数 引用计数案例 执行结果: 导致引用计数 +1 的情况 导致引用计数-1 的情况 循环引用导致内存泄露 执行结果 分代回收 垃圾回收 gc 模块 常用函数: 引用计数 Python 语言默认采用的垃圾收集机制是『引用计数法 Reference Counting』,该算法最早 George E. Collins 在 1960 的时候首次提出,50 年后的今天,该算法依然被很多编程语言使用. 引用计数法的原理是:每个对象维护一个ob_ref字段,用来记录该对象当前被引用的次数,每当新的

  • Python 垃圾回收机制详解

    目录 1. 引用计数 2. 标记-清除 3. 分代回收 4. 其他 4.1 JNI(Java Native Interface) 总结 Python 的GC模块主要运用了引用计数来跟踪和回收垃圾:通过"标记-清除"解决容器对象可能产生的循环引用问题:通过分代回收以空间换时间进一步提高垃圾回收的效率. 也即采用"引用计数"为主(实时性,一旦没有引用,内存就直接释放了),"标记-清除"与"分代收集"两种机制为辅的策略.      

  • python语言开发垃圾回收机制原理教程

    目录 一.什么是垃圾回收机制 二.为什么要有垃圾回收机制 三.垃圾回收机制的原理 1.引用计数 直接引用 间接引用 2.栈区 / 堆区 3.总结 四.标记清除 1.循环引用问题(也叫交叉引用) 2.循环引用导致的结果 3.解决方法 : 清除-标记 五.分代回收 1.效率问题 2.解决方法 : 分代回收 分代 回收 总结 一.什么是垃圾回收机制 垃圾回收机制(简称GC), 解释器自带的一种机制 它是一种动态存储管理技术,自动释放不再被程序引用的对象所占用的内存空间 二.为什么要有垃圾回收机制 程序

  • linux下多线程中的fork介绍

    目录 问题提出: 情况(1)fork在创建子线程之前 情况(2)fork在创建子线程之后 情况(3)子线程中的fork 结论: 问题提出: 回想一下:当一个程序只有主线程的时候调用fork,此时fork会创建出的子进程也会只有一条线程: 那要是把fork放入多线程的程序中呢? 我们来试验下: 情况(1)fork在创建子线程之前 代码: #include <stdio.h> #include <pthread.h> #include <unistd.h> void* pt

  • Python垃圾回收是怎么实现的

    目录 什么是垃圾回收 Python中的垃圾回收机制 引用计数 循环引用 标记清除解除循环引用 分代回收 总结 什么是垃圾回收 垃圾回收(GC) 大家应该多多少少都了解过,什么是垃圾回收呢?垃圾回收GC的全拼是 Garbage Collection,在维基百科的定义是:在计算机科学中,垃圾回收(英语:Garbage Collection,缩写为GC)是一种自动的内存管理机制.当一个电脑上的动态内存不再需要时,就应该予以释放,以让出内存,这种内存资源管理,称为垃圾回收.我们都知道在C/C++里用户需

  • Linux多线程中fork与互斥锁过程示例

    目录 问题提出: (一)初次尝试 (二)理性分析 (三)解决问题 (1)使用pthread_join() (2)使用phread_atfork()注册一个fork之前的判断 问题提出: 我们有这样一个问题:在一个多线程程序中创建子进程并且让子线程和子进程去获取一把全局变量的锁,输出子线程得到锁,然后解锁,子进程拿到锁,然后解锁: (一)初次尝试 代码: #include <stdio.h> #include <unistd.h> #include <pthread.h>

  • Python垃圾回收及Linux Fork

    目录 1.Linux fork简介 1.Copy-On-Write策略增加Python多进程内存占用的原因 3.解决办法 前言: 在口袋助理看到了其他部门的同事针对Python2内存占用做的一点优化工作,自己比较感兴趣,遂记录下. 1.Linux fork简介 fork是Linux提供的创建子进程的系统调用.为了优化创建进程速度,Linux内核使用了Copy-on-Write的方式去创建进程,所谓Copy-on-Write是指执行fork之后,内核并不立即给子进程分配物理内存空间,而是让子进程的

  • Python垃圾回收及Linux Fork

    目录 1.Linux fork简介 1.Copy-On-Write策略增加Python多进程内存占用的原因 3.解决办法 前言: 在口袋助理看到了其他部门的同事针对Python2内存占用做的一点优化工作,自己比较感兴趣,遂记录下. 1.Linux fork简介 fork是Linux提供的创建子进程的系统调用.为了优化创建进程速度,Linux内核使用了Copy-on-Write的方式去创建进程,所谓Copy-on-Write是指执行fork之后,内核并不立即给子进程分配物理内存空间,而是让子进程的

  • python垃圾回收机制(GC)原理解析

    这篇文章主要介绍了python垃圾回收机制(GC)原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 今天想跟大家分享的是关于python的垃圾回收机制,虽然本人这会对该机制没有很深入的了解, 但是本着热爱分享的原则,还是囫囵吞枣地坐下记录分享吧, 万一分享的过程中开窍了呢.哈哈哈. 首先还是做一下概述吧: 我们都知道, 在做python的语言编程中, 相较于java, c++, 我们似乎很少去考虑到去做垃圾回收,内存释放的工作, 其实是p

  • 详细分析Python垃圾回收机制

    引入 为什么要有垃圾回收机制 Python中的垃圾回收机制简称(GC),我们在程序的运行中会产生大量的变量用于保存数据,而有时候有些变量已经没有用了就需要被清理释放掉该变量所占据的内存空间.在一些较为低级的语言中(比如:C语言,汇编语言)对于内存空间的释放是需要编程人员来手动进行的,这种与底层硬件直接打交道的操作是十分的危险与繁琐的,而基于C语言开发而来的Python为了解决掉这种顾虑则自带了一种垃圾回收机制,从而让开发人员不必过分担心内存的使用情况而可以全身心的投入到开发中去. >>>

  • 谈谈python垃圾回收机制

    什么是垃圾回收机制? 首先,咱先来解释名词,垃圾回收是不是就是将没用的,废弃的东西回收起来. 在坐的各位都没有女朋友对吧,那难以想象你们的房间会是一个什么样子,可能会有很多垃圾,很凌乱,自己也不收拾.那当你有了女朋友了就不一样了,她会帮你收拾房间,把没用的垃圾都给你扔掉. 那在我们Python当中的垃圾回收承担的就是女朋友的角色,你们想象一下,你现在有一个轻度强迫症的女朋友一刻不停的跟在你的背后打扫卫生,你一放下脏碟子或者垃圾什么的,就已经帮你清理.打扫了 所以垃圾回收机制就是自动帮助我们管理内

  • 详解Python垃圾回收机制和常量池的验证

    Python的引入 人类认识世界是从认识世界中的一个又一个实物开始,然后再对其用语言加以描述.例如当中国人看到苹果时,便会用中文"苹果"加以描述,而用英语的一些国家则会用"apple"加以描述. 以上说到的中文和英文都是人类认识并描述世界的一个工具,而在计算机的世界中,为了让计算机去认知世界,从而帮助人类完成更多的任务.在计算机领域中也发展了语言这个工具,从早期的机器语言到汇编语言再到现在使用范围较广的高级语言.而我们接下来要介绍的Python则属于高级语言这一分支

  • 理解Python垃圾回收机制

    一.垃圾回收机制 Python中的垃圾回收是以引用计数为主,分代收集为辅.引用计数的缺陷是循环引用的问题. 在Python中,如果一个对象的引用数为0,Python虚拟机就会回收这个对象的内存. #encoding=utf-8 __author__ = 'kevinlu1010@qq.com' class ClassA(): def __init__(self): print 'object born,id:%s'%str(hex(id(self))) def __del__(self): pr

  • Python垃圾回收机制三种实现方法

    引用计数 Python语言默认采用的垃圾收集机制是『引用计数法 Reference Counting』,该算法最早George E. Collins在1960的时候首次提出,50年后的今天,该算法依然被很多编程语言使用. 『引用计数法』的原理是:每个对象维护一个ob_ref字段,用来记录该对象当前被引用的次数,每当新的引用指向该对象时,它的引用计数ob_ref加1,每当该对象的引用失效时计数ob_ref减1,一旦对象的引用计数为0,该对象立即被回收,对象占用的内存空间将被释放 缺点:它的缺点是需

随机推荐