php script bellek sızıntısı

5 Cevap php

Ben bir mysql sorgu çalışan bir php script, sonra sonucu döngüler, ve bu döngü içinde de birkaç sorguları çalışır var:

    $sqlstr = "SELECT * FROM user_pred WHERE uprType != 2 AND uprTurn=$turn ORDER BY uprUserTeamIdFK";
    $utmres = mysql_query($sqlstr) or trigger_error($termerror = __FILE__." - ".__LINE__.": ".mysql_error());
    while($utmrow = mysql_fetch_array($utmres, MYSQL_ASSOC)) {
// some stuff happens here    
//  echo memory_get_usage() . " - 1241<br/>\n";
        $sqlstr = "UPDATE user_roundscores SET ursUpdDate=NOW(),ursScore=$score WHERE ursUserTeamIdFK=$userteamid";
        if(!mysql_query($sqlstr)) {
            $err_crit++;
            $cLog->WriteLogFile("Failed to UPDATE user_roundscores record for user $userid - teamuserid: $userteamid\n");
            echo "Failed to UPDATE user_roundscores record for user $userid - teamuserid: $userteamid<br>\n";
            break;
        }
    unset($sqlstr);
    //  echo memory_get_usage() . " - 1253<br/>\n";
// some stuff happens here too
}

Güncelleştirme sorgusu başarısız asla.

For some reason, between the two calls of memory_get_usage, there is some memory added. Because the big loop runs about 500.000 or more times, in the end it really adds up to alot of memory. Is there anything I'm missing here?
could it herhaps be that the memory is not actually added between the two calls, but at another point in the script?

Edit: some extra info: Before the loop it's at about 5mb, after the loop about 440mb, and every update query adds about 250 bytes. (the rest of the memory gets added at other places in the loop). The reason I didn't post more of the "other stuff" is because its about 300 lines of code. I posted this part because it looks to be where the most memory is added.

5 Cevap

Kimden php.net memory_get_usage manual:

Parametreler

real_usage Set this to TRUE to get the real size of memory allocated from system. If not set or FALSE only the memory used by emalloc() is reported.

Beklediğim gibi ayarlamak true Bu parametre ile, komut dosyası, bellek hiçbir artış gösterdi.

Bir "bellek bitkin" hatası ile komut öldürüyor Bu bellek sızıntısı, sadece bir sorun olacaktır. PHP mutlu çöp kendi üzerinde herhangi unusued nesneler / değişkenleri toplayabilir, ama ona sahip kadar toplayıcı tekme olmaz - çöp toplama çok pahalı bir işlem olabilir.

Size sürekli aynı nesneler / değişkenleri yeniden olsanız bile bellek kullanımı tırmanış görmek normaldir - bu bellek kullanımı toplayıcı kadar yangın ve temiz bir ev olacağı belli bir düzeyi aşarsa kadar değil.

Ben size gruba userids batched ve her biri daha fazla kayıtları değişen, az güncelleştirme yayınladı eğer işler çok daha hızlı koşmak yapabilir sanıyorum. örneğin aşağıdakileri yapın:

GÜNCELLEME user_roundscores ursUpdDate = NOW () WHERE ursUserTeamIdFK IN (id1, id2, ID3, ID4, ID5, vs ..) SET

bunun yerine tek-update-kullanıcı başına yapıyor. DB arayüz katmanı sayesinde daha az yuvarlak gezileri ve sunucu üzerinde daha fazla zaman = daha hızlı çalışıyor.

Eğer bir açıklama içinde söylemek yanı sıra, şimdi milyonlarca kullanıcı bu genişleyen etkisini düşünün. Bir milyon bireysel güncellemeleri çalıştırmak için zaman önemsiz olmayan bir miktarda alacak, böylece NOW() "sabit" olmayacak. Bu tam bir çalışma yapmak için 5 dakika sürer, o zaman ursUpdDate damgalarının çok çeşitli almak için gidiyoruz. Bir sunucu tarafı değişken bir tek NOW() çağrıyı önbellekleme düşünün ve bu değişkene karşı güncellemelerini isteyebilirsiniz:

 SELECT @cachednow :p NOW();
 UPDATE .... SET ursUpDate = @cachednow WHERE ....;

Her tekrarında ek kullanılan bellek görüyor olabilirsiniz nedenle parçası PHP (henüz) çöp başvurulan artık topladığı şeylerin olmasıdır.

I think you should try calling mysql_free_result() at some point during the loop. - yorum Gönderen:

It's worth noting that mysql_query() only returns a resource for SELECT, SHOW, EXPLAIN, and DESCRIBE queries.

Yani bir güncelleştirme sorgusu için ücretsiz hiçbir sonuç yoktur.

Neyse, sizin yaklaşım ile başlamak için iyi değil. Mysqli doğrudan veritabanına satırları güncelleme (daha iyi) yerine ifadeleri paramterized, ya da deneyin. Döngüde SQL tüm tek UPDATE deyimi ile ele olabilir gibi görünüyor.

unset çağrı alakasız / anlamsızdır. Bazı etkisi olabilir - mysql_free_result ile olsa deneyin.