Его небольшой код для теста:
$strings = array('<big string here (2 Mb)'); $arr = array(); //--> memory usage here is 17.1Mb (checked by pmap) echo memory_get_usage();//0.5Mb //(i know, that other 16.6Mb of memory used by process are php libraries) for($i = 0; $i < 20; ++$i) { $strings_local = array_merge($strings, array($i)); $arr[$i] = $strings_local; unset($strings_local); } //--> memory usage here is 20.3Mb (checked by pmap) echo memory_get_usage();//3.7Mb //so, here its all ok, 17.1+3.2 = 20.3Mb for($i = 0; $i < 20; ++$i) { unset($arr[$i]); } //--> memory usage here is 20.3Mb (checked by pmap) //BUT?? i UNSET this variables... echo memory_get_usage();//0.5Mb
Таким образом, похоже, что php не является свободной памятью, даже если вы unset()
свою переменную. Как я могу освободить память после ее отмены?
У PHP есть сборщик мусора, который заботится об управлении памятью для вас, что влияет на использование памяти (процесса) несколькими способами.
Во-первых, при проверке использования памяти процесса вне процесса, даже если PHP видит, что какая-то память будет освобождена, она не может быть возвращена обратно в ОС для целей оптимизации, связанных с распределением памяти. Это уменьшает накладные расходы от непрерывных освобождений и распределений, что легче происходит с языками GC'd, поскольку процедура распределения не отображается в реальной программе.
По этой причине, даже если вы вызываете gc_collect_cycles()
вручную, память может вообще не быть освобождена для ОС, а повторно использована для будущих распределений. Это приводит к тому, что PHP видит меньшее использование памяти, чем тот процесс, который на самом деле используется, из-за раннего большого резервирования, которое никогда не доходит до ОС.
Во-вторых, из-за природы сбора мусора, память не может быть сразу освобождена после того, как она не используется программой. Вызов gc_collect_cycles()
приведет к немедленному освобождению памяти, но ее следует считать ненужным и не работает, если в вашем скрипте возникла утечка памяти (или что-то в PHP).
Для того, чтобы знать, что происходит, выполнение проверки строки за строкой (например, с помощью трассировки функции Xdebug) даст вам более полное представление о том, как PHP (а точнее, ваша программа) видит использование памяти.
Объединив это, чтобы pmap
проверять внешний процесс (например, ваши команды pmap
), можно было бы сказать, действительно ли PHP освобождает любую память в любой момент после ее резервирования.