我的PHP嵌套循环使用太多内存

时间:2012-07-23 19:15:03

标签: php memory-management loops foreach simplexml

我正在尝试编写一个处理大量数据的实用程序,而内存是一个因素。不幸的是,每次我运行这组循环时,它都会吃掉apx。 14MB的内存,因为它执行了数千次,即使使用unset()调用(是的,我知道他们不会完全清理内存,这就是为什么我在问这个问题)。我想知道是否有更简单的方法来做到这一点。目前的工作代码:

        $qr = array();
        foreach($XML->row as $row)
        {
         $ra = array();
         foreach($row as $key => $value)
         {
         $ra[$key] = $value[0];
         unset($key,$value);
         }
        $qr[] = $ra;
        unset($row,$ra);
        }
        unset($XML);
        return $qr;

另一种尝试是做到这一点,但它落后了。谁知道我做错了什么?

        $qr = array();
        while(list(,$row) = each($XML->row))
        {
         $ra = array();
         while(list($key,$value) = each($row))
         {
         $ra[$key] = $value[0];
         unset($key,$value);
         }
        $qr[] = $ra;
        unset($row,$ra);
        }
        unset($XML);
        return $qr;

基本上在第一个循环中,我只是尝试进行基本的数组/对象迭代。在第二个循环中,我试图遍历每个数组值并获得第一个元素,同时保持对象/数组索引关联。我似乎最初是这样写的,因为它是唯一有用的东西(因为它循环通过SimpleXML对象)。任何关于加速这件事或弄清楚如何让它不吃记忆的提示都将不胜感激。

我正在寻找垃圾收集或更高效代码的解决方案。我不打算替换SimpleXML,因为不需要它。 更清楚,我正在寻找:

  • 迭代SimpleXML对象而不需要调用内部循环的方法(这只是因为我做了$ value [0]。为什么这是必要的?
  • 一种更有效的方式(速度或内存方式),用于迭代数据

3 个答案:

答案 0 :(得分:1)

如果你想使用更少的内存我建议你开始查看SAX parser。这是example。使用SAX开发解析器更加困难,但它比SimpleXML更有效,你可以用它来解析大的xml文件。

答案 1 :(得分:1)

您的内存负载很高,因为SimpleXML在解析时会将整个文档加载到内存中。所以你的unset()调用只是递减reference count,因为数据仍然存在于内存中,所以它不会被释放。这是使用SimpleXML的结果:其好处是文档在内存中并表示为PHP对象。

如果您想减少内存使用量,则需要使用其他内容,例如XMLReaderXML Parser。这些是基于SAX或基于事件的,它不会将XML文件加载到内存中,而是一次一个元素地遍历树。由于您似乎没有使用类似XPath的东西,因此这是您更好的选择。

答案 2 :(得分:1)

这不是您从SimpleXML对象访问数据的方式。我看到你正在使用index [0]来获取对象的每个部分的字符串内容并将其视为一个数组。 这不是一个数组,它是一个对象。这是你应该如何访问字符串数据......示例:http://php.net/manual/en/simplexml.examples-basic.php#example-5095

这样的事情可以解决问题:

    $qr = array();
    foreach($XML->row as $row)
    {
     $ra = array();
     $ra['name'] = $value->name;
     $ra['name2'] = $value->name2;
     //Add a line for each element name, etc...

    $qr[] = $ra;
    unset($row,$ra);
    }
    unset($XML);
    return $qr;

它也会摆脱你的内循环并节省你的记忆。