Symfony 1.4 bir görevi çalışırken daha az bellek kullanımı nasıl?

8 Cevap php

Ben Symfony 1.4 ve Doctrine kullanıyorum.

So far I had no problem running tasks with Symfony. But now that I have to import a pretty big amount of data and save them in the database, I get the infamous

"Fatal Error: Allowed memory size of XXXX bytes exhausted"

Bu ithalat sırasında sadece, yeni nesneler yaratmak birkaç alanları belirleme ve bunları saklıyorum.

Ben verileri kaydetme ben yaratıyorum nesnelerin sayısı ile ilgili bir şey vardır eminim. Bu nesneleri unsetting olsa bir şey yapmaz.

Symfony'de bellek kullanımını sınırlamak için en iyi yöntemler var mı?

8 Cevap

Ben bu geldim, ve ben gerçekten Doktrini geniş bellek kullanımı ile yardımcı bulundu teknikleri bir çift var.

1: Mümkünse, Doktrin sorgu için bir dizi aşağı sonuçları hidrat. Örneğin aşağıdaki gibi yapabilirsiniz:

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

Bu büyük nesneleri oluşturmak DEĞİL Doktrini zorlar, ancak bunun yerine bir dizi için azaltır. Açıkçası bunu yaparsanız, size yöntemleri vb aramak için yeteneğini kaybetmek aklınızda, bu yüzden alan değerleri okuma vb için kullanıyorsanız eğer, bu sadece iyi

2: yürütme sonra sonuçları boşaltın. Bu Doktrini dokümanlar küçücük bir alanda belgelenmiş, ama gerçekten ben kullanıyordum ithalat görevi yardım etti:

$query->free();

İşte bu. Ayrıca oluşturduğu tüm dairesel başvuruları kaldırmak için oluşturduğunuz nesneler, örneğin $myObj->free(); ve bu güçler Doktrin yapabilirsiniz. Döngüsel başvurular otomatik olarak PHP kapsamı veya unset() aracılığıyla itibaren bir nesnenin silinmesi üzerine PHP 5.3 'ten kurtulmuş, ama önce bunu kendiniz yapmanız gerekir unutmayın.

Bunları kullandıktan sonra siliniyor değişkenler de unset(), aksi dairesel refs açık olmayacak gibi olsa da, belirtildiği gibi yukarıda free() yöntemi ile birlikte bunu, yardımcı olur.

Bu deneyin:

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

belirtildiği gibi

php/symfony/doctrine memory leak?

Ürdün Feldstein benim değil yanıtla.

Üzgünüm, bu bir geç cevap olduğunu biliyorum, ama birisi yardımcı olabilir.

Başka bir potansiyel olarak büyük bellek tasarrufu emin Symfony'nin hata ayıklama modu, bu görev için etkin değil yapmaktır. Uzun çalışan görevlerin bir çift ben bu satırı eklendi ve ben hidrasyon modu gibi şeyler optimize sonra bile% 40 yaklaşık RAM kullanımını azaltmak.

sfConfig::set('sf_debug', false);

Bir görev içinde kullanılan bellek miktarını azaltmak için bir başka ipucu sorgu profilcisini devre dışı bırakmak için. Sorguları büyük bir sayı daha ve daha fazla bellek kullanarak görevi yapmak eğilimindedir.

Bunu yapmak için aşağıdaki satırları ekleyerek database.yml yapılandırma dosyasında yeni bir görev ortamı oluşturmak:

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

Sonra kurulum görev "görev" ortamında çalıştırmak için. Sorguları bir döngü içinde iseniz sabit bellek kullanımını tutmaya yardımcı olacaktır.

Onlar uzun bir süre çalıştırmak ve balon eğilimi bir çok veri kullanırsanız, ve ben çok ayrı bir PHP süreçlerini çağrılan bir sarıcı yapılmış olsa bile, bu 'yapmadım - Ben symfony PHP toplu işler ile aynı sorunu yaşadım t yardım.

Bu nedenle, ben Perl'ın DBI ile benim büyük toplu iş yazılabilir ettik ve onlar, güvenilir ve yönetilebilir demektir.

Ben sadece sempati ve benim deneyimi sunan, bu en iyi cevap olduğunu düşündüren değilim. PHP daha iyi davranmaya yapmak için bir yolu muhtemelen vardır.

Doktrin Query üzerinde fetchone ile Dikkat (). Bu işlev çağrısı SQL üzerinde "Limiti 1" append olmaz

Sadece DB tek kayıtları almak gerekiyorsa, emin olun:

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

Bellek kullanımı büyük masaya bırakılan muazzam.

Önce sonra ilk öğeyi döndürür () bir koleksiyon olarak DB alıp fetchone görebiliyordu.

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;
}

Içine bakarak Ayrıca değer:

gc_collect_cycles - varolan herhangi bir çöp döngülerinin Kuvvetleri koleksiyonu

Ayrıca sadece gerçekten ihtiyacı olan için sorguda (seçin) alanlarını sınırlamak için deneyin.

Örneğin gibi bir şey kullanabilirsiniz:

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

yerine:

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