使用嵌套for循环分解内存占用PHP脚本

时间:2013-06-07 02:13:25

标签: php memory-management for-loop

我正在尝试使用此脚本构建零件编号表。我很快就没有记忆了。我已经注释掉了我甚至无法得到的循环:

 foreach ($mat_codes as $mat_code) {
     for ($n = 0; $n < count($shape_codes); $n++){
        for ($d1 = 0; $d1 <= 12; $d1++){
          for ($d1_dec = 1; $d1_dec <= 16; $d1_dec++){
            for ($d2 = 0; $d2 <= 12; $d2++){
              //for ($d2_dec = 1; $d2_dec <= 16; $d2_dec++){
                $build_part = (object) NULL;
                $build_part = $mat_code->part_code;
                $build_part .= $shape_codes[$n]->part_code;
                $build_part .= '.';
                if ($d1 != 0) {
                  $build_part .=  $d1 . '-';
                }
                $build_part .= $d1_dec;
                $build_part .= '.';
                //  if ($d2 != 0) {
                //    $build_part .=  $d2 . '-';
                //  }
                // $build_part .= $d2_dec;
                // $build_part .= '.';

                // * save $build_part to MYSQL * //
             //}
           }
        }
      }
    }
  }

不出所料,这是回归

  

PHP致命错误:允许的内存大小为134217728 byuseuseted   (试图分配71个字节)

对于记录,$mat_codes中约有16个值,$shape_codes中有16个值。根据我的计算,我试图仅在这个例子中创建692,224个零件号。我想我会增加更多,最多可达3400万。恕我直言,尝试通过为工作分配更多内存来完成这项工作将是愚蠢的。我的问题 - 当然 - 我如何将这个剧本分成更小的块?

修改 我有一个解决方法。我道歉它超出了我在原始问题中定义的范围。我没有提到这只是一个潜在零件编号表。特别是,零件编号系统的逻辑允许的所有潜在零件编号。而不是在等待使用的准备好的部件号的主列表,我想我可能更好地验证部件编号逻辑的新部件输入,像could_this_be_a_part_number($input)这样的函数。它可以只针对部件编号逻辑测试输入的字符串,而不是让我需要检查一些主表。

编辑x2:对不起,这是最糟糕的。我将unset($build_part)移到了最里面的for循环中。问题是我试图在Drupal中使用开发函数在未设置之前打印出每个$ build_part - dpm($build_part)。该脚本运行正常,它试图构建一个打印了许多部件号的网页,这就是破坏脚本的原因。

1 个答案:

答案 0 :(得分:1)

首先: $ build_part 似乎不应该是一个对象,因为你把它视为一个字符串,所以不要像那样初始化它。

$build_part = NULL;就足够了。

其次:我们不知道您希望如何将数据保存在数据库中,但您可以(以我的原始答案某种方式提出)构建查询,将其发送到数据库然后继续

现在让我们来看看你的代码:

$i = 0;
foreach ($mat_codes as $mat_code) {
     for ($n = 0; $n < count($shape_codes); $n++){
        for ($d1 = 0; $d1 <= 12; $d1++){
          for ($d1_dec = 1; $d1_dec <= 16; $d1_dec++){
            for ($d2 = 0; $d2 <= 12; $d2++){
              for ($d2_dec = 1; $d2_dec <= 16; $d2_dec++){
                $i++;
                $build_part = (object) NULL;
                $build_part = $mat_code->part_code.".";
                $build_part .= $shape_codes[$n]->part_code;
                $build_part .= '.';
                if ($d1 != 0) {
                  $build_part .=  $d1 . '-';
                }
                $build_part .= $d1_dec;
                $build_part .= '.';
                 if ($d2 != 0) {
                   $build_part .=  $d2 . '-';
                 }
                $build_part .= $d2_dec;
                // echo "$i $build_part <br>";
                // * save $build_part to MYSQL * //
             }
             // This is first triggered when the count reaches 16 items
             echo "--- lvl 5<br>";
           }
           // 208 items
           echo "--- lvl 4<br>";
        }
        // 3328 items
        echo "--- lvl 3<br>";
      }
      echo "--- lvl 2<br>";
    }
    echo "--- lvl 1<br>";
}

我已经确定(并且您可以在其他地方执行此操作) 3级符号作为您可以向数据库发送一些预先构建的MySQL查询的点。 类似的东西:

$mysqli->query("INSERT INTO parts ( {PART_ID {1}}

另外看一下这个MySQL命令:INSERT DELAYED,我想也许(sic!)在你的情况下非常有用。

$ very_long_string 将构建在最内循环中,如:

) VALUES $very_long_string;");

并且最后(在我们创建并发送最终查询之前)我们将删除最后一个逗号:

$very_long_string .= "('$build_part'),";

然后将3000多项长查询发送到数据库。然后取消设置($ very_long_string)并重新开始。

所以我想最终代码看起来像这样:

$very_long_string = rtrim($very_long_string, ",");

阅读您的编辑后编辑:我当然正在处理您想填充数据库的事实:D ..如果您需要验证功能,那么这是另一个故事。< / p>