PHP内存调试



对于我的一个项目,我需要导入一个非常大的文本文件(~950MB)。我正在使用Symfony2&我的项目的原则2。

我的问题是,我得到的错误像:

Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 24 bytes)

即使我将内存限制增加到1GB,也会出现错误。

我试图通过使用XDebug和KCacheGrind(作为PHPEdit的一部分)来分析这个问题,但我并不真正理解这些值:(

我正在寻找一种工具或方法(快速和简单,因为我没有太多时间)来找出为什么内存被分配而没有再次释放。

编辑

要清除一些东西,这里是我的代码:

$handle = fopen($geonameBasePath . 'allCountries.txt','r');
        $i = 0;
        $batchSize = 100;
        if($handle) {
            while (($buffer = fgets($handle,16384)) !== false) {
                if( $buffer[0] == '#') //skip comments
                    continue;
                //split parts
                $parts = explode("t",$buffer);

                if( $parts[6] != 'P')
                    continue;
                if( $i%$batchSize == 0 )    {
                    echo 'Flush & Clear' . PHP_EOL;
                    $em->flush();
                    $em->clear();
                }
                $entity = $em->getRepository('MyApplicationBundle:City')->findOneByGeonameId( $parts[0] );
                if( $entity !== null)   {
                    $i++;
                    continue;
                }
                //create city object
                $city = new City();
                $city->setGeonameId( $parts[0] );
                $city->setName( $parts[1] );
                $city->setInternationalName( $parts[2] );
                $city->setLatitude($parts[4] );
                $city->setLongitude( $parts[5] );
                $city->setCountry( $em->getRepository('MyApplicationBundle:Country')->findOneByIsoCode( $parts[8] ) );
                $em->persist($city);
                unset($city);
                unset($entity);
                unset($parts);
                unset($buffer);
                echo $i . PHP_EOL;

                $i++;
            }
        }
        fclose($handle);

我尝试过,但没有任何帮助:

  1. fgets添加第二个参数
  2. 增加内存_限制
  3. 松开vars

增加内存限制是不够的。当导入这样的文件时,可以缓冲读取。

$f = fopen('yourfile');
while ($data = fread($f, '4096') != 0) {
    // Do your stuff using the read $data
}
fclose($f);

更新:

当使用ORM时,您必须明白,在flush调用之前,实际上不会在数据库中插入任何内容。这意味着所有这些对象都由标记为"待插入"的ORM存储。只有在进行flush调用时,ORM才会检查集合并开始插入。

解决方案1:经常冲洗。而且很清楚。

解决方案2:不要使用ORM。转到纯SQL命令。它们将比object+ORM解决方案占用更少的内存。

33554432是32MB

更改php.ini中的内存限制,例如75MB

memory_limit = 75M

并重新启动服务器

与其简单地读取文件,不如逐行读取文件。每次你读一行,你都应该处理你的数据。不要试图把所有的东西都放在记忆中。你会失败的。原因是,虽然可以将TEXT文件放在ram中,但不能同时将数据作为php对象/变量/whathaveyou,因为php本身需要更大的内存。

我的建议是a) 读取新行,b) 解析行中的数据c) 创建要存储在数据库中的新对象d) 转到步骤a,先取消旧对象的设置或重用它的内存

相关内容

  • 没有找到相关文章

最新更新