PHP内存调试

Fri*_*ido 1 php xdebug kcachegrind symfony doctrine-orm

对于我的项目之一,我需要导入一个非常大的文本文件(~950MB).我正在为我的项目使用Symfony2和Doctrine 2.

我的问题是我得到的错误如下:

Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 24 bytes)
Run Code Online (Sandbox Code Playgroud)

如果我将内存限制增加到1GB,甚至会出现错误.

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

我正在寻找一种工具或方法(Quick and Simple,因为我没有太多时间)来找出为什么分配内存而不是再次释放.

编辑

要清除这里的一些内容,我的代码是:

$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);
Run Code Online (Sandbox Code Playgroud)

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

  1. 将第二个参数添加到fgets
  2. 增加memory_limit
  3. 取消vars

i.a*_*iel 5

增加内存限制是不够的.导入这样的文件时,缓冲读数.

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

更新:

使用ORM时,您必须了解在刷新调用之前,数据库中实际上没有插入任何内容.意味着所有这些对象都由ORM标记为"待插入".只有在进行刷新调用时,ORM才会检查集合并开始插入.

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

解决方案2:不要使用ORM.转到纯SQL命令.它们占用的内存远远少于object + ORM解决方案.