代码之家  ›  专栏  ›  技术社区  ›  Guillaume Flandre

在symfony 1.4中运行任务时如何使用较少的内存?

  •  17
  • Guillaume Flandre  · 技术社区  · 15 年前

    我用的是symfony 1.4和district。

    到目前为止,我和symfony一起运行任务没有问题。 但是现在我不得不导入大量的数据并将它们保存在数据库中,这让我声名狼藉

    “致命错误:允许的内存大小为” XXXX字节已用完”

    在这个导入过程中,我只创建新对象,设置一些字段并保存它们。

    我很确定这与我在保存数据时创建的对象数量有关。但是,取消设置这些对象并不起任何作用。

    symfony中是否有限制内存使用的最佳实践?

    8 回复  |  直到 13 年前
        1
  •  11
  •   richsage    15 年前

    我发现了这一点,我发现有一些技术对教义的广泛记忆使用起到了真正的帮助。

    1:在可能的情况下,将条令查询结果简化为一个数组。您可以这样做,例如:

    $query = self::createQuery("q")->
      ...
      ->setHydrationMode(Doctrine::HYDRATE_ARRAY)
      ->execute();
    

    这迫使教义不创建大对象,而是将其减少到一个阵列。显然要记住,如果这样做,您将失去调用方法等的能力,因此只有当您使用它来读取字段值等时,这才是好的。

    2:执行后释放结果。这在条令文档的一小部分中有记录,但它确实帮助我完成了我使用的导入任务:

    $query->free();
    

    就这样。您也可以在已创建的对象上执行此操作,例如 $myObj->free(); 这迫使教义删除所有它创建的循环引用。注意,在通过php作用域或 unset() 但是在那之前你需要自己去做。

    在使用变量后取消设置变量也会有所帮助,尽管这样做与 free() 上述方法,如 未设置() 否则不会清除循环引用。

        2
  •  4
  •   Community CDub    8 年前

    试试这个:

    Doctrine_Manager::connection()->setAttribute(Doctrine_Core::ATTR_AUTO_FREE_QUERY_OBJECTS, true );
    

    如上文所述

    php/symfony/doctrine memory leak?

    乔丹·费尔德斯坦的回答不是我的。

        3
  •  4
  •   Remiz    13 年前

    减少任务中使用的内存量的另一个提示是禁用查询探查器。大量的查询往往会使任务占用越来越多的内存。

    为此,请通过添加以下行在database.yml配置文件中创建新的任务环境:

    task:
      doctrine:
        class: sfDoctrineDatabase
        param:
          profiler: false
    

    然后将任务设置为在“任务”环境中运行。如果查询处于循环中,它应该有助于保持内存使用的稳定。

        4
  •  2
  •   ybull    14 年前

    对不起,我知道这是一个迟交的答复,但可以帮助某人。

    另一个潜在的巨大内存节省程序是确保symfony的调试模式没有为该任务启用。在一些长时间运行的任务中,我添加了这一行,即使在我优化了水化模式之后,它也减少了大约40%的RAM使用。

    sfConfig::set('sf_debug', false);
    
        5
  •  1
  •   Nathan    14 年前

    对于symfony的php批处理作业,我也遇到过同样的问题——如果它们运行了很长时间,并且使用了大量的数据,那么它们往往会膨胀,即使我制作了一个调用了许多单独的php进程的包装器,也没有用。

    因此,我用Perl的DBI重写了我的大批量作业,它们是可靠的和可管理的。

    我不是说这是最好的答案,只是同情和提供我的经验。也许有一种方法可以让PHP表现得更好。

        6
  •  1
  •   snakewa    13 年前

    在条令查询中注意fetchone()。此函数调用不会在SQL上附加“limit 1”

    如果只需要从数据库中获取一条记录,请确保:

    $q->limit(1)->fetchOne() 
    

    内存使用量在大表上急剧下降。

    您可以看到fetchone()将首先作为集合从db中提取,然后返回第一个元素。

    public function fetchOne($params = array(), $hydrationMode = null)
    {
        $collection = $this->execute($params, $hydrationMode);
    
        if (is_scalar($collection)) {
            return $collection;
        }
    
        if (count($collection) === 0) {
            return false;
        }
    
        if ($collection instanceof Doctrine_Collection) {
            return $collection->getFirst();
        } else if (is_array($collection)) {
            return array_shift($collection);
        }
    
        return false;
    }
    
        7
  •  0
  •   dsomnus    14 年前

    也值得研究:

    gc_collect_cycles 强制收集任何现有垃圾循环

        8
  •  0
  •   Del Pedro    13 年前

    还可以尝试将查询中的(select)字段限制为您真正需要的字段。

    例如,使用如下内容:

    $query = self::createQuery("q")->
      ->select('id','title','price')
      ...
    

    而不是:

    $query = self::createQuery("q")->
      ->select('*')
      ...