After testing, breaking up memory intensive code into a separate function allows the garbage collection to work.
For example the original code was like:-
while(true){
//do memory intensive code
}
can be turned into something like:-
function intensive($parameters){
//do memory intensive code
}
while(true){
intensive($parameters);
}Собирање циклуси
Почист и полокален преглед на PHP референцата, со задржана структура од PHP.net и подобра читливост за примери, секции и белешки.
Собирање циклуси
Референца за `features.gc.collecting-cycles.php` со подобрена типографија и навигација.
Собирање циклуси
Традиционално, механизмите за управување со меморија со броење на референци, како што претходно го користеше PHP, не успеваат да ги решат тековите на меморијата со циркуларни референци; сепак, од 5.3.0, PHP го имплементира синхрониот алгоритам од » Конкурентно собирање циклуси во системи со броење на референци документот кој го решава тој проблем.
Целосно објаснување за тоа како работи алгоритамот би било малку надвор од опсегот на овој дел, но основите се објаснети овде. Пред сè, мора да воспоставиме неколку основни правила. Ако рефбројот се зголеми, тој сè уште е во употреба и затоа не е ѓубре. Ако рефбројот се намали и достигне нула, zval може да се ослободи. Ова значи дека циклусите на ѓубре можат да се создадат само кога аргументот на рефбројот се намалува на вредност различна од нула. Второ, во циклус на ѓубре, можно е да се открие кои делови се ѓубре со проверка дали е можно да се намали нивниот рефброј за еден, а потоа да се провери кои од zval-овите имаат рефброј од нула.
За да се избегне потребата да се повикува проверката на циклуси на ѓубре со секое можно намалување на рефбројот, алгоритамот наместо тоа ги става сите можни корени (zval-ови) во „баферот за корени“ (обележувајќи ги како „пурпурни“). Исто така, осигурува дека секој можен корен на ѓубре завршува во баферот само еднаш. Дури кога баферот за корени ќе се наполни, механизмот за собирање започнува за сите различни zval-ови внатре. Погледнете го чекор А на сликата погоре.
Во чекор Б, алгоритамот извршува длабинско пребарување на сите можни корени за да го намали за еден рефбројот на секој zval што ќе го најде, осигурувајќи се да не го намали рефбројот на истиот zval двапати (со обележување како „сиви“). Во чекор В, алгоритамот повторно извршува длабинско пребарување од секој корен јазол, за повторно да го провери рефбројот на секој zval. Ако открие дека рефбројот е нула, zval се обележува како „бел“ (син на сликата). Ако е поголем од нула, го враќа намалувањето на рефбројот за еден со длабинско пребарување од таа точка натаму, и тие повторно се обележуваат како „црни“. Во последниот чекор (Д), алгоритамот поминува низ баферот за корени отстранувајќи ги корените на zval од таму, и во меѓувреме, проверува кои zval-ови биле обележани како „бели“ во претходниот чекор. Секој zval обележан како „бел“ ќе биде ослободен.
Сега кога имате основно разбирање за тоа како работи алгоритамот, ќе погледнеме како ова се интегрира со PHP. Стандардно, собирачот на ѓубре на PHP е вклучен. Сепак, постои php.ini поставување што ви овозможува да го промените ова: zend.enable_gc.
Кога собирачот на ѓубре е вклучен, алгоритамот за пронаоѓање циклуси опишан погоре се извршува секогаш кога баферот за корени ќе се наполни. Баферот за корени има фиксна големина од 10.000 можни корени (иако можете да го промените со менување на GC_THRESHOLD_DEFAULT константата во
Zend/zend_gc.c во изворниот код на PHP, и повторно компилирање на PHP). Кога собирачот на ѓубре е исклучен, алгоритамот за пронаоѓање циклуси никогаш нема да се изврши. Сепак, можните корени секогаш ќе бидат запишани во баферот за корени, без разлика дали механизмот за собирање ѓубре е активиран со оваа поставка за конфигурација.
Ако баферот за корени се наполни со можни корени додека механизмот за собирање ѓубре е исклучен, понатамошните можни корени едноставно нема да бидат запишани. Тие можни корени што не се запишани никогаш нема да бидат анализирани од алгоритамот. Ако беа дел од циклус на циркуларна референца, тие никогаш нема да бидат исчистени и би создале теков на меморија.
Причината зошто можните корени се запишуваат дури и ако механизмот е оневозможен е затоа што е побрзо да се запишат можните корени отколку да се проверува дали механизмот е вклучен секогаш кога може да се најде можен корен. Самиот механизам за собирање и анализа на ѓубре, сепак, може да одземе значително време.
Покрај менувањето на zend.enable_gc поставката за конфигурација, исто така е можно да се вклучи и исклучи механизмот за собирање ѓубре со повикување gc_enable() or gc_disable() односно. Повикувањето на тие функции има исто дејство како вклучување или исклучување на механизмот со поставката за конфигурација. Исто така е можно да се присили собирањето на циклуси дури и ако баферот за можни корени сè уште не е полн. За ова, можете да го користите gc_collect_cycles() функцијата. Оваа функција ќе врати колку циклуси биле собрани од алгоритамот.
Причината зад можноста за вклучување и исклучување на механизмот, и самостојно иницирање на собирање циклуси, е тоа што некои делови од вашата апликација може да бидат многу чувствителни на време. Во тие случаи, можеби нема да сакате да се активира механизмот за собирање ѓубре. Се разбира, со исклучување на собирањето ѓубре за одредени делови од вашата апликација, ризикувате да создадете текови на меморија бидејќи некои можни корени можеби нема да се вклопат во ограничениот бафер за корени. Затоа, веројатно е мудро да се повика gc_collect_cycles() непосредно пред да го повикате gc_disable() за да се ослободи меморијата што може да се изгуби преку можни корени што веќе се запишани во баферот за корени. Ова потоа остава празен бафер за да има повеќе простор за складирање на можни корени додека механизмот за собирање циклуси е исклучен.
Белешки од корисници 3 белешки
── Unused Objects ─── ─ In use Objects
↓ ↓ ↓
_____________________________________
|□□□□□□□□□□□□□□□□□|██■■■■■■■■■■■■■■■■|
|□□□□□□□□□□□□□□□□□|██■■■■■■■■■■■■■■■■|
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
▲ ▲
Unreferenced Referenced
Objects Objects
█ Memory leakMemory leak: meaning you keep a reference to it thus preventing the GC from collecting it.