我有一个遍历数据库行的do / while循环。因为它在处理100000行时运行了很多天,所以内存消耗对于保持检查很重要,否则会崩溃。现在每次迭代都会增加大约4kb的脚本内存使用量。我正在使用memory_get_usage()来监控使用情况。
我在每次迭代中首先取消了循环中使用的每个变量,所以我真的不知道我还能做什么。我的猜测是,每次迭代时都会收集一些数据,这就是消耗4kb的内存。我知道4kb听起来并不多,但是当你有100000次迭代时很快就会加起来。
有人可以建议另一种方法来浏览大量的数据库行,或者如何以某种方式消除这种“内存泄漏”?
修改的 这是UPDATED循环代码。上面只有几个require_once()s。
$URLs = new URLs_url(db());
$c = new Curl;
$c->headers = 1;
$c->timeout = 60;
$c->getinfo = true;
$c->follow = 0;
$c->save_cookies = false;
do {
// Get url that hasn't been checked for a week
$urls = null;
// Check week old
$urls = $URLs->all($where)->limit(10);
foreach($urls as $url) {
#echo date("d/m/Y h:i").' | Checking '.$url->url.' | db http_code: '.$url->http_code;
// Get http code
$c->url = $url->url;
$data = $c->get();
#echo ' - new http_code: '.$data['http_code'];
// Save info
$url->http_code = $data['http_code'];
$url->lastchecked = time();
$URLs->save($url);
$url = null;
#unset($c);
$data = null;
#echo "\n".memory_get_usage().' | ';
echo "\nInner loop memory usage: ".memory_get_usage();
}
echo "\nOuter loop memory usage: ".memory_get_usage();
} while($urls);
一些记录两个循环中内存消耗的行为:
Inner loop memory usage: 611080
Inner loop memory usage: 612452
Inner loop memory usage: 613788
Inner loop memory usage: 615124
Inner loop memory usage: 616460
Inner loop memory usage: 617796
Inner loop memory usage: 619132
Inner loop memory usage: 620500
Inner loop memory usage: 621836
Inner loop memory usage: 623172
Outer loop memory usage: 545240
Inner loop memory usage: 630680
Inner loop memory usage: 632016
Inner loop memory usage: 633352
Inner loop memory usage: 634688
Inner loop memory usage: 636088
Inner loop memory usage: 637424
Inner loop memory usage: 638760
Inner loop memory usage: 640096
Inner loop memory usage: 641432
Inner loop memory usage: 642768
Outer loop memory usage: 556392
Inner loop memory usage: 640416
Inner loop memory usage: 641752
Inner loop memory usage: 643088
Inner loop memory usage: 644424
Inner loop memory usage: 645760
Inner loop memory usage: 647096
Inner loop memory usage: 648432
Inner loop memory usage: 649768
Inner loop memory usage: 651104
Inner loop memory usage: 652568
Outer loop memory usage: 567608
Inner loop memory usage: 645924
Inner loop memory usage: 647260
Inner loop memory usage: 648596
Inner loop memory usage: 649932
Inner loop memory usage: 651268
Inner loop memory usage: 652604
Inner loop memory usage: 653940
Inner loop memory usage: 655276
Inner loop memory usage: 656624
Inner loop memory usage: 657960
Outer loop memory usage: 578732
答案 0 :(得分:2)
这个位应该只在循环之前发生一次:
$c = new Curl;
$c->headers = 1;
$c->timeout = 60;
...
$c->getinfo = true;
$c->follow = 0;
$c->save_cookies = false;
编辑:哦,整个事情都包含在do / while循环中。 /捂脸
编辑2:还有这个重要的一点:
unset($ class_object)不会释放 对象分配的资源。如果 用于循环,创建和 摧毁对象,这可能很容易 导致资源问题。明确地 调用析构函数来绕过析构函数 问题
http://www.php.net/manual/en/function.unset.php#98692
编辑3:
这是什么?不能以某种方式将其移到循环之外吗?$URLs = new URLs_url(db());
编辑4:
暂时尝试删除这些行。
$url->http_code = $data['http_code'];
$url->lastchecked = time();
$URLs->save($url);
答案 1 :(得分:0)
我认为你的核心问题是你只是在外循环中清理东西。
例如, $c = new Curl
将为内循环的每次迭代分配内存到堆,但是你只是unset
最后一个实例。我会在内循环的 end 中unset
你可以做任何事情($c
,$data
。
答案 2 :(得分:0)
问题可能是
$c = new Curl
是否可以在循环外部实例化Curl,然后在内部继续重用相同的实例。如果需要,可以在循环中将所有字段重置为null。
我有类似的问题。取消设置无效 - 事实证明垃圾收集是垃圾。当我重用对象时,它很好(好吧,它因各种原因而破坏,所以我最终在Java中重新实现)。
答案 3 :(得分:0)
这可能会或可能不会对你有所帮助,但回到2000年时,我有一个客户,他的互联网真的很慢,并希望在本地完成他所有的网站cms更新,并在完成后更新为live。当时在win xp上的IIS上,我找不到从60秒增加脚本超时的方法,并且通常需要2分钟才能完成更新,因此显然会超时。
要解决这个问题,我会让脚本更新一定数量的行,这些行保证在一分钟内安全执行,然后使用参数从哪里继续调用,依此类推,直到所有行都更新为止。也许你可以尝试类似的情况吗?
也许在调用之前运行它一段时间,或者在你的情况下,可能检查内存,并在使用率过高时重定向?
我使用过这样的东西:
脚本顶部:
$started = microtime(true);
然后在你的循环中:
if((microtime(true)-$started) > ($seconds_to_redirect)) {
//call script with parameter
}
这是我能想到的全部。