我有一个很长的内存密集型循环。我无法一次性运行它,因为我的服务器设置了执行时间限制,或者我的内存不足。
我想把这个循环分成更小的块。
我有一个想法是将循环拆分为较小的块,然后设置一个位置标题以使用新的启动条件重新加载脚本。
MY OLD SCRIPT(Pseudocode。我知道下面的缺点)
for($i=0;$i<1000;$i++)
{
//FUNCTION
}
我的新脚本
$start=$_GET['start'];
$end=$start+10;
for($i=$start;$i<$end;$i++;)
{
//FUNCTION
}
header("Location:script.php?start=$end");
然而,我的新脚本成功运行了几次迭代,然后我收到服务器错误“Too many redirects”
有解决方法吗?有人可以提出更好的策略吗?
我在共享服务器上,因此无法增加内存分配或脚本执行时间。
我想要一个PHP解决方案。
感谢。
答案 0 :(得分:2)
“重定向太多”是一个浏览器错误,因此PHP解决方案是使用cURL或标准流来加载初始页面并让它遵循所有重定向。您必须从没有超时限制的计算机运行此程序(例如使用CLI)
要考虑的另一件事是使用AJAX。页面上的一段JavaScript将运行您的脚本,从脚本中收集输出并确定是停止(计算结束)还是继续(从X开始)。这样你也可以创建一个漂亮的进度表; - )
答案 1 :(得分:0)
首先,如果不知道你在循环中做了什么,很难告诉你实际解决问题的最佳方法。但是,如果你想执行一些需要很长时间的事情,我的建议是设置一个cron作业,并让它一次完成一小部分。该脚本将记录它停止的位置,下次启动时,它可以读取日志以确定从哪里开始。
编辑:如果你已经死了反对cron,并且你不太关心用户体验,你可以这样做:
让页面加载类似于上面的cron作业。除非经过这么多秒或迭代,否则请停止脚本。显示刷新元标记或javascript刷新。这样做直到任务完成。
答案 2 :(得分:0)
一般情况下,如果我必须多遍迭代并且它有相当数量的数据,我使用“延迟加载”类型的应用程序,如:
for($i=$start;$i<$end;$i++;)
{
$data_holder[] = "adding my big data chunks!";
if($i % 5 == 1){
//function to process data
process_data($data_holder); // process that data like a boss!
unset($data_holder); // This frees up the memory
}
}
// Now pick up the stragglers of whatever is left in the data chunk
if(count($data_holder) > 0){
process_data($data_holder);
}
通过这种方式,您可以继续遍历数据,但不会填满内存。您可以使用块,然后取消设置数据,处理块,取消设置数据等。以帮助防止内存。就执行时间而言,这取决于您需要做多少/编写脚本的效率。
基本前提 - “以较小的块处理数据以避免内存问题。保持设计简单,以保持快速。”
答案 3 :(得分:0)
你如何在循环中将一个条件放入每100次迭代中休眠一次?
for ($i = 0; $i < 1000; $i++)
{
if ($i % 100 == 0)
sleep(1800) //Sleep for half an hour
}
答案 4 :(得分:0)
您可能希望调查forking child processes来完成工作。这些子进程可以在自己的内存空间中以较小的块进行工作,而父进程会触发多个子进程。这通常由Gearman处理,但可以不用。
在Dealnews的开发者网站上查看Forking PHP。它有一个库和一些示例代码,以帮助管理需要生成子进程的代码。
答案 5 :(得分:0)
由于你有这些限制,我认为你使用的方法可行。可能是您的浏览器试图变得聪明,并且不允许您重定向您刚刚访问的页面。它可能试图阻止无限循环。
你可以尝试
在两个相同(或别名)的脚本之间来回重定向。
另一种浏览器。
让您的脚本输出带有刷新标记的HTML页面,例如:
<meta http-equiv="refresh" content="1; url=http://example.com/script.php?start=xxx">