php / symfony / doktrin bellek sızıntısı?

8 Cevap php

Ben Symfony 1.4 ve doktrin 1.2 kullanarak bir veritabanına nesneleri toplu ekleme ile ilgili sorunlar yaşıyorum.

Benim modeli (genellikle 50 ila 200.000 kadar değişen) tip "Cupo" çeşitli nesneler vardır, her biri "Sektör" denilen nesnenin belirli bir tür vardır. Bu nesneler oldukça küçük; sadece kısa bir tanımlayıcı bir dize ve bir ya da iki tamsayı. Sektörlerin bir grup kullanıcı tarafından oluşturulan zaman, otomatik olarak veritabanına "Cupo" tüm bu örneklerini eklemek gerekir. Bir şey yanlış giderse durumda, her şeyi geri almak için bir doktrin işlem kullanıyorum. Sorun php bellek dolmadan sadece yaklaşık 2000 örnekleri oluşturabilirsiniz olmasıdır. Bu şu anda az 100 bayt kullanmak nesneleri işlemek için fazlasıyla yeterli olmalıdır 128MB sınırı vardır. Ben 512 kadar hafıza limitini artırmak denedim, ama php yine çöker ve bu sorunu çözmüyor. Ben doğru toplu ekleme yapıyor ya da daha iyi bir yolu var muyum?

İşte hata var:

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 71 bytes) in /Users/yo/Sites/grifoo/lib/vendor/symfony/lib/log/sfVarLogger.class.php on line 170

Ve burada kod:

public function save($conn=null){

    $conn=$conn?$conn:Doctrine_Manager::connection();

    $conn->beginTransaction();


    try {
        $evento=$this->object;


        foreach($evento->getSectores() as $s){

            for($j=0;$j<$s->getCapacity();$j++){

                $cupo=new Cupo();
                $cupo->setActivo($s->getActivo());
                $cupo->setEventoId($s->getEventoId());
                $cupo->setNombre($j);
                $cupo->setSector($s);

                $cupo->save();

            }
        }

        $conn->commit();
        return;
    }
    catch (Exception $e) {
        $conn->rollback();
        throw $e;
    }

Bir kez daha, bu kod az 1000 nesneler için çalışıyor, ama 1500 daha büyük bir şey başarısız olur. Yardımlarınız için teşekkürler.

8 Cevap

Yaparak çalıştı

$cupo->save();
$cupo->free();
$cupo = null;

(Ama benim kod yerine) Ve ben hala bellek taşmaları alıyorum. Diğer fikirler, SO?

Update:

Benim databases.yml yeni bir ortam yarattı, bu gibi görünüyor:

all:
  doctrine:
    class: sfDoctrineDatabase
    param:
      dsn: 'mysql:host=localhost;dbname=.......'
      username: .....
      password: .....
      profiler: false

profiler: false giriş normalde yaptığınız her sorgunun bir kopyasını tutar, öğretinin sorgu günlüğü devre dışı bırakır. Bu bellek sızıntısını durmadı, ama ben onsuz olarak ithal benim veri üzerinden yaklaşık iki kat kadar elde edebildi.

Update 2

Ben eklendi

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

benim sorguları çalıştırmadan önce, ve değişti

$cupo = null;

karşı

unset($cupo);

Ve şimdi benim komut uzak mutlu çalkalama olmuştur. Ben RAM bu sefer çalıştırmadan bitecek eminim.

Update 3

Evet. İşte kazanan combo.

Ben sadece Symfony 1.4 ve aşağıdaki ayarı ile komut hogging bellek durdurdu "daemon" did adres:

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

Her kaydetme sonra unset($cupo); çalışın. Bu yardım olmalıdır. Bir başka şey komut dosyası bölmek ve bazı toplu işlem yapmaktır.

Genellikle ile bellek sızıntıları neden olan döngüsel başvuru kırmaya çalışın

$cupo->save();

$cupo->free(); //this call

gibi described Doktrin kılavuzda.

Bir symfony görev için, ben de bu konuya karşı karşıya ve şeyler takip yapılır. Bu benim için çalıştı.

  • Hata ayıklama modunu devre dışı. Db bağlantı başlatmak için önce aşağıdaki ekle

    sfConfig::set('sf_debug', false);
    
  • Db bağlantısı için ayarlanabilir otomatik sorgu nesnesi ücretsiz nitelik

    $connection->setAttribute(Doctrine_Core::ATTR_AUTO_FREE_QUERY_OBJECTS, true );
    
  • Kullandıktan sonra serbest, tüm nesne

    $object_name->free()
    
  • Unset tüm diziler kullanımdan sonra unset($array_name)

  • Check all doctrine queries used on task. Free all queries after use. $q->free() (This is a good practice for any time of query using.)

Hepsi bu. Biri yardımcı olabilir umuyoruz.

Benim için, ben sadece böyle görevi başlatıldı ettik:

// initialize the database connection
$databaseManager = new sfDatabaseManager($this->configuration);
$connection = $databaseManager->getDatabase($options['connection'])->getConnection();
$config = ProjectConfiguration::getApplicationConfiguration('frontend', 'prod', true);
sfContext::createInstance($config);

(WITH PROD CONFIG)
and use free() after a save() on doctrine's object

Bellek 25Mo stabildir

memory_get_usage=26.884071350098Mo

debian squeeze üzerinde php 5.3 ile

Periyodik yakın ve yeniden açın bağlantı - emin değilim ama neden PDO başvuruları istinat görünüyor.

Ne benim için çalışıyor bu gibi free yöntemini çağırarak geçerli:

$cupo->save();
$cupo->free(true); // free also the related components
unset($cupo);