gpt4 book ai didi

php - 为什么这个简单的 php 脚本会泄漏内存?

转载 作者:IT王子 更新时间:2023-10-28 23:30:29 27 4
gpt4 key购买 nike

为了避免将来在 php 程序(drupal 模块等)中发生内存泄漏,我一直在使用会泄漏内存的简单 php 脚本。

能否请 php 专家帮我找出这个脚本导致内存使用量不断攀升的原因?

尝试自己运行它,更改各种参数。结果很有趣。这里是:

<?php

function memstat() {
print "current memory usage: ". memory_get_usage() . "\n";
}

function waste_lots_of_memory($iters) {
$i = 0;
$object = new StdClass;
for (;$i < $iters; $i++) {
$object->{"member_" . $i} = array("blah blah blha" => 12345);
$object->{"membersonly_" . $i} = new StdClass;
$object->{"onlymember"} = array("blah blah blha" => 12345);
}
unset($object);
}

function waste_a_little_less_memory($iters) {
$i = 0;
$object = new StdClass;
for (;$i < $iters; $i++) {

$object->{"member_" . $i} = array("blah blah blha" => 12345);
$object->{"membersonly_" . $i} = new StdClass;
$object->{"onlymember"} = array("blah blah blha" => 12345);

unset($object->{"membersonly_". $i});
unset($object->{"member_" . $i});
unset($object->{"onlymember"});

}
unset($object);
}

memstat();

waste_a_little_less_memory(1000000);

memstat();

waste_lots_of_memory(10000);

memstat();

对我来说,输出是:

current memory usage: 73308
current memory usage: 74996
current memory usage: 506676

[编辑以取消设置更多对象成员]

最佳答案

unset()不会释放变量使用的内存。当“垃圾收集器”(在引号中,因为 PHP 在 5.3.0 版之前没有真正的垃圾收集器,只是一个主要用于原语的内存释放例程)认为合适时释放内存。

此外,从技术上讲,您不需要调用 unset()因为 $object 变量仅限于您的函数范围。

这是一个演示差异的脚本。我修改了您的 memstat() 函数以显示自上次调用以来的内存差异。

<?php
function memdiff() {
static $int = null;

$current = memory_get_usage();

if ($int === null) {
$int = $current;
} else {
print ($current - $int) . "\n";
$int = $current;
}
}

function object_no_unset($iters) {
$i = 0;
$object = new StdClass;

for (;$i < $iters; $i++) {
$object->{"member_" . $i}= array("blah blah blha" => 12345);
$object->{"membersonly_" . $i}= new StdClass;
$object->{"onlymember"}= array("blah blah blha" => 12345);
}
}

function object_parent_unset($iters) {
$i = 0;
$object = new StdClass;

for (;$i < $iters; $i++) {
$object->{"member_" . $i}= array("blah blah blha" => 12345);
$object->{"membersonly_" . $i}= new StdClass;
$object->{"onlymember"}= array("blah blah blha" => 12345);
}

unset ($object);
}

function object_item_unset($iters) {
$i = 0;
$object = new StdClass;

for (;$i < $iters; $i++) {

$object->{"member_" . $i}= array("blah blah blha" => 12345);
$object->{"membersonly_" . $i}= new StdClass;
$object->{"onlymember"}= array("blah blah blha" => 12345);

unset ($object->{"membersonly_" . $i});
unset ($object->{"member_" . $i});
unset ($object->{"onlymember"});
}
unset ($object);
}

function array_no_unset($iters) {
$i = 0;
$object = array();

for (;$i < $iters; $i++) {
$object["member_" . $i] = array("blah blah blha" => 12345);
$object["membersonly_" . $i] = new StdClass;
$object["onlymember"] = array("blah blah blha" => 12345);
}
}

function array_parent_unset($iters) {
$i = 0;
$object = array();

for (;$i < $iters; $i++) {
$object["member_" . $i] = array("blah blah blha" => 12345);
$object["membersonly_" . $i] = new StdClass;
$object["onlymember"] = array("blah blah blha" => 12345);
}
unset ($object);
}

function array_item_unset($iters) {
$i = 0;
$object = array();

for (;$i < $iters; $i++) {
$object["member_" . $i] = array("blah blah blha" => 12345);
$object["membersonly_" . $i] = new StdClass;
$object["onlymember"] = array("blah blah blha" => 12345);

unset ($object["membersonly_" . $i]);
unset ($object["member_" . $i]);
unset ($object["onlymember"]);
}
unset ($object);
}

$iterations = 100000;

memdiff(); // Get initial memory usage

object_item_unset ($iterations);
memdiff();

object_parent_unset ($iterations);
memdiff();

object_no_unset ($iterations);
memdiff();

array_item_unset ($iterations);
memdiff();

array_parent_unset ($iterations);
memdiff();

array_no_unset ($iterations);
memdiff();
?>

如果您使用对象,请确保类实现了 __unset()为了允许 unset()适当清理资源。尽量避免使用可变结构类,例如 stdClass 或将值分配给不在类模板中的成员,因为分配给这些成员的内存通常不会被正确清除。

PHP 5.3.0 及更高版本具有更好的垃圾收集器,但默认情况下它是禁用的。要启用它,您必须调用 gc_enable()一次。

关于php - 为什么这个简单的 php 脚本会泄漏内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1145775/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com