백엔드 개발 PHP 튜토리얼 php垃圾回收之回收计策和算法

php垃圾回收之回收计策和算法

Jun 13, 2016 pm 12:03 PM
root unset xdebug zval

php垃圾回收之回收策略和算法

一、垃圾回收实现方式

? ? ?在以前的php中用到的是引用计数机制处理垃圾回收问题,但是这个机制存在一个弊端,就是无法处理循环引用引起的内存泄露。然而在php5.3.0以后的版本中(包含5.3.0)使用了专门GC机制(同步算法)清理垃圾,来处理这个内存泄露问题。下面就是介绍它是如何实现的:

? ??首先要了解几个基本的准则:

1:如果一个zval的refcount增加,那么此zval还在使用,不属于垃圾。

2:如果一个zval的refcount减少到0,?那么zval可以被释放掉,属于垃圾。

3:如果一个zval的refcount减少之后大于0,那么此zval还不能被释放,此zval可能成为一个垃圾。

? ? ?只有在准则3下,GC才会把zval收集起来,然后通过新的算法来判断此zval是否为垃圾。那么如何判断这么一个变量是否为真正的垃圾呢?简单的说,就是对此zval中的每个元素进行一次refcount减1操作,操作完成之后,如果zval的refcount=0,那么这个zval就是一个垃圾。这个原理咋看起来很简单,但是又不是那么容易理解,下面通过结构图来深入理解:


? ? ?A:为了避免每次变量的refcount减少的时候都调用GC的算法进行垃圾判断,此算法会先把所有前面准则3情况下的zval节点放入一个节点(root)缓冲区(root buffer),并且将这些zval节点标记成紫色,同时算法必须确保每一个zval节点在缓冲区中之出现一次。当缓冲区被节点塞满的时候,GC才开始开始对缓冲区中的zval节点进行垃圾判断。

? ? ?B:当缓冲区满了之后,算法以深度优先对每一个节点所包含的zval进行减1操作,为了确保不会对同一个zval的refcount重复执行减1操作,一旦zval的refcount减1之后会将zval标记成灰色。需要强调的是,这个步骤中,起初节点zval本身不做减1操作,但是如果节点zval中包含的zval又指向了节点zval(环形引用),那么这个时候需要对节点zval进行减1操作。

? ? ?C:算法再次以深度优先判断每一个节点包含的zval的值,如果zval的refcount等于0,那么将其标记成白色(代表垃圾),如果zval的refcount大于0,那么将对此zval以及其包含的zval进行refcount加1操作,这个是对非垃圾的还原操作,同时将这些zval的颜色变成黑色(zval的默认颜色属性)

? ? ?D:遍历zval节点,将C中标记成白色的节点zval释放掉。

二、举例详解垃圾回收过程

? ? ?通过上面的说明,大家可能已经有了一定的印象,那实际应用中是如何具体操作的呢?下面就通过例子说明:

? ? ①在刚刚声明变量并赋值的情况下,其实就相当于准则1(如果一个zval的refcount增加,那么此zval还在使用,不属于垃圾),变量不是垃圾,也不会进行gc检查。

$a = "one";$b = array();$b[] = $a;$b[] = & $b;$c = "two";//声明了三个变量$a、$b、$c。这个时候refcount都是增加的情况,变量不是垃圾也不会放入到root缓冲器等待垃圾检查。xdebug_debug_zval( 'a' );  xdebug_debug_zval( 'b' );  xdebug_debug_zval( 'c' );  //输出分别如下:a: (refcount=2, is_ref=0)='one'b: (refcount=2, is_ref=1)=array (     0 => (refcount=2, is_ref=0)='one',     1 => (refcount=2, is_ref=1)=... )  c: (refcount=1, is_ref=0)='two'
로그인 후 복사

? ?②在上面的基础上,我们调用了unset()函数释放变量b和c。如下:

unset($b);unset($c);xdebug_debug_zval( 'a' ); //输出如下:a: (refcount=2, is_ref=0)='one'
로그인 후 복사

? ? ?调用unset函数后,$b和$c对应容器中的refcount都会减1,但是他们的效果却不相同:先看$c调用unset($c)后,$c的refcount就编程了0,符合准则2,则$c对应的zval容器就是垃圾会被回收;再看$b调用unset($b)后,但是$b的第1个引用仍然指向$b所对应的zval容器,只不过$b对应的zval容器的refcount会减1,值会从2变成1。这时候容器的refcount虽然减1,但仍然不为零,则符合准则3,会把$b对应的zval,放入到root缓冲区中。等待gc垃圾校验操作,也就是进入到了(二)中的(A)情况。

? ? ?③在往后的操作就是(二)中描述的了。经历(二)中的ABCD过程后,变量$b对应的zval容器会被释放,完成了垃圾回收,也解决了循环引用的内存泄露问题。

三、垃圾回收器配置使用

? ? ?在PHP中,GC默认是开启的,你可以通过ini文件中的?zend.enable_gc 项来开启或则关闭GC。当GC开启的时候,垃圾分析算法将在节点缓冲区(roots buffer)满了之后启动。缓冲区默认可以放10,000个值,当然你也可以通过修改Zend/zend_gc.c中的GC_ROOT_BUFFER_MAX_ENTRIES?来改变这个数值,需要重新编译链接PHP。当GC关闭的时候,垃圾分析算法就不会运行,但是相关节点还会被放入节点缓冲区,这个时候如果缓冲区节点已经放满,那么新的节点就不会被记录下来,这些没有被记录下来的节点就永远也不会被垃圾分析算法分析。如果这些节点中有循环引用,那么有可能产生内存泄漏。之所以在GC关闭的时候还要记录这些节点,是因为简单的记录这些节点比在每次产生节点的时候判断GC是否开启更快,另外GC是可以在脚本运行中开启的,所以记录下这些节点,在代码运行的某个时候如果又开启了GC,这些节点就能被分析算法分析。当然垃圾分析算法是一个比较耗时的操作。

??? 在PHP代码中我们可以通过gc_enable()和gc_disable()函数来开启和关闭GC,也可以通过调用gc_collect_cycles()在节点缓冲区未满的情况下强制执行垃圾分析算法。这样用户就可以在程序的某些部分关闭或则开启GC,也可强制进行垃圾分析算法。?

? ? ?

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

Video Face Swap

Video Face Swap

완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

슈퍼유저로 Ubuntu에 로그인 슈퍼유저로 Ubuntu에 로그인 Mar 20, 2024 am 10:55 AM

Ubuntu 시스템에서는 루트 사용자가 일반적으로 비활성화되어 있습니다. 루트 사용자를 활성화하려면 passwd 명령을 사용하여 비밀번호를 설정한 다음 su- 명령을 사용하여 루트로 로그인할 수 있습니다. 루트 사용자는 무제한 시스템 관리 권한을 가진 사용자입니다. 그는 파일, 사용자 관리, 소프트웨어 설치 및 제거, 시스템 구성 변경에 액세스하고 수정할 수 있는 권한을 가지고 있습니다. 루트 사용자와 일반 사용자 사이에는 분명한 차이가 있습니다. 루트 사용자는 시스템에서 가장 높은 권한과 더 넓은 제어 권한을 갖습니다. 루트 사용자는 일반 사용자가 할 수 없는 중요한 시스템 명령을 실행하고 시스템 파일을 편집할 수 있습니다. 이 가이드에서는 Ubuntu 루트 사용자, 루트로 로그인하는 방법, 일반 사용자와 어떻게 다른지 살펴보겠습니다. 알아채다

Nginx 구성에서 루트 지시문과 별칭 지시문의 차이점은 무엇입니까? Nginx 구성에서 루트 지시문과 별칭 지시문의 차이점은 무엇입니까? May 12, 2023 pm 12:16 PM

루트와 별칭은 모두 위치 모듈에서 정의할 수 있으며 요청된 리소스의 실제 경로를 지정하는 데 사용됩니다. 예: location/i/{root/data/w3;} 요청 http://foofish.net/i /top.gif 이 주소를 사용하는 경우 서버의 해당 실제 리소스는 /data/w3/i/top.gif 파일입니다. 참고: 실제 경로는 루트에 지정된 값과 위치에 지정된 값을 더한 값입니다. 그리고 별칭은 이름과 같습니다. 별칭으로 지정된 경로는 위치의 별칭입니다. 위치 값을 어떻게 작성하든 리소스의 실제 경로는 다음과 같이 별칭으로 지정된 경로입니다.

Python을 사용하여 Windows에서 긴 경로 파일을 삭제하는 단계별 방법 Python을 사용하여 Windows에서 긴 경로 파일을 삭제하는 단계별 방법 Apr 12, 2023 pm 01:31 PM

0x01 기사 배경 최근 작성자 회사의 비즈니스 시스템 스토리지가 한계에 가까워지고 있으며 비즈니스 시스템 A에 여러 하위 시스템 A1, A2, A3...이 포함되어 있으므로 곧 서버를 실행할 수 없게 됩니다. 설계상의 이유로 저장소 파일은 모두 동일한 상위 디렉터리에 저장됩니다. 유일한 차이점은 서로 다른 하위 시스템에서 생성된 파일 및 폴더의 이름이 하위 시스템의 이름으로 시작한다는 것입니다. 예를 들어, A1 하위 시스템에서 생성된 파일 이름은 모두 A1xxxxxx​이고, A2 하위 시스템에서 생성된 파일 이름은 모두 A2xxxxx입니다. 이제 서버 공간을 확보하기 위해 일부 하위 시스템의 기록 파일을 삭제해야 합니다. 수십 테라바이트의 데이터가 함께 저장되어 있으므로 프로그램 자동화만 사용할 수 있습니다.

Linux에서 루트 사용자 이름을 변경하는 방법 Linux에서 루트 사용자 이름을 변경하는 방법 May 18, 2023 pm 07:50 PM

1. CentOS를 예로 들어 로그인 후 /etc/passwd, /etc/shadow를 수정하고, 첫 번째 줄부터 시작하는 루트를 새로운 사용자 이름(예: admin)으로 변경하고, 수정 후 wq!를 통해 저장합니다. 2. 수정하고 저장한 후, 서버를 다시 시작해야 적용됩니다. 파일의 권한을 확인하면 다음과 같이 계정 열이 admin으로 변경된 것을 확인할 수 있습니다. 참고: Linux에서 가장 높은 관리 권한을 가진 기본 사용자입니다. 루트이고 uid는 0입니다. 시스템에서는 uid만 인식하므로 uid가 0인 한 시스템은 최고 관리 사용자로 간주됩니다. 그러나 응용 프로그램에 특정 문제가 있을 수 있습니다. 일부 소프트웨어는 기본적으로 루트 사용자를 사용하므로 소프트웨어 응용 프로그램에 대한 이해가 제한적인 경우

휴대폰 루팅의 장점과 단점 휴대폰 루팅의 장점과 단점 Jul 06, 2023 pm 04:53 PM

전화기를 루팅하면 다음과 같은 장점이 있습니다. 1. 시스템을 백업할 수 있습니다. 2. 고급 프로그램을 사용할 수 있습니다. 3. 시스템 프로그램을 수정하고 삭제할 수 있습니다. 4. SD 카드에 프로그램을 설치할 수 있습니다. 시스템 글꼴 등 단점: 1. 휴대폰이 루팅된 후에는 트로이 목마 바이러스에 감염되기 쉽습니다. 2. 불완전성 및 소프트웨어 호환성 문제로 인해 시스템 손상이 발생할 수 있습니다. 3. 휴대폰이 루팅된 후 소프트웨어가 실수로 시스템 파일을 삭제합니다. 4. 휴대폰 루팅 등으로 인해 사용자의 개인정보가 유출될 위험이 있습니다.

프로덕션 서버에서 XDebug를 활성화하면 PHP 속도가 느려지나요? 프로덕션 서버에서 XDebug를 활성화하면 PHP 속도가 느려지나요? Sep 22, 2023 pm 10:41 PM

예, XDebug와 같은 디버거는 PHP 서버 성능을 저하시킬 수 있습니다. 이것이 디버거가 서버 환경에 배치되지 않는 이유입니다. 불필요한 오버헤드를 피하기 위해 다양한 환경에 배포됩니다. 이미 프로덕션 중인 애플리케이션에는 디버그 메시지를 표시할 수 없습니다. 디버깅 동작이 서버에 추가되면 디버깅 엔진이 PHP 프로세스에 연결됩니다. 중단점에서 중지하라는 메시지 수신을 시작하지만 이는 다른 프로세스에 성능 저하를 주어 PHP 파서를 중지하므로 필수 동작은 아닙니다. 반면에 디버거를 설치하면 프로덕션 환경에서 사용하기 위한 것이 아니기 때문에 서버에서 포트를 여는 경향이 있습니다. 서버에서 포트를 여는 것은 해커가 엿볼 수 있도록 문을 여는 것만큼 나쁩니다.

PHP는 변수를 어떻게 저장하나요? zval 구조를 이해하시나요? PHP는 변수를 어떻게 저장하나요? zval 구조를 이해하시나요? May 26, 2022 am 09:47 AM

PHP에서 변수를 정의할 때 유형을 선언할 필요가 없습니다. 처음에는 변수 $a에 정수 값을 할당하고 나중에 다른 유형으로 쉽게 변경할 수 있습니다. 그렇다면 이 변수 ​​$a는 PHP 소스 코드에 어떻게 저장됩니까? 이 질문을 염두에 두고 PHP의 소스 코드를 살펴보겠습니다.

PHP8.0의 디버깅 라이브러리: Xdebug PHP8.0의 디버깅 라이브러리: Xdebug May 14, 2023 am 08:09 AM

디버깅은 PHP 개발에서 피할 수 없는 부분입니다. 개발자가 자신의 코드를 보다 쉽게 ​​디버그할 수 있도록 돕기 위해 PHP8.0은 디버깅 라이브러리에 Xdebug라는 매우 유용한 도구를 도입했습니다. 이 기사에서는 Xdebug의 주요 기능 중 일부와 이를 사용하여 PHP 디버깅 프로세스를 단순화하는 방법을 소개합니다. Xdebug는 PHP 애플리케이션의 오류를 캡처하고 자세한 오류 스택 추적 정보와 사용 중인 변수를 제공할 수 있는 오픈 소스 디버깅 도구입니다. 개발자가 코드를 감지하고 문제를 해결하는 데 도움이 됩니다.

See all articles