Versio

Memory Limit exceeded

Overzicht Reageren

Wouter Hardeman

Wouter Hardeman

15/06/2011 21:39:41
Quote Anchor link
Goedenavond,

Ik heb een (zwaar) script gemaakt die 4000+ YouTube video's moet scannen en in een database stoppen. M'n probleem is nu het memory limit.

Quote:
Fatal error: Allowed memory size of 209715200 bytes exhausted (tried to allocate 47 bytes) in C:\xampp\htdocs\gamerspawnfeed\Zend\Gdata\App\Base.php on line 380


Ik heb php.ini al aangepast naar 8196M, maar dit lijkt niet te werken... Heeft iemand een oplossing?

Alvast bedankt!
 
PHP hulp

PHP hulp

25/05/2012 09:06:00
Gesponsorde koppelingen:
 
Pieter van Linschoten

Pieter van Linschoten

15/06/2011 21:45:50
Quote Anchor link
Hahaha, als je server meer dan 8 GB intern geheugen heeft, zou het geen probleem moeten zijn.

Je kan er voor zorgen dat je het geheugen zo optimaal mogelijk gebruikt.
Dit doe je door zo efficient mogelijk je processen af te handelen.

Verder kun je natuurlijk in één keer proberen alle 8,000 filmpjes te scannen, maar je kan het ook verdelen in parten van bijvoorbeeld 100 stuks. Je laat het script bijhouden welke filmpjes je al hebt gehad.

Laat een cronjob het script aanroepen en verder gaan bij het laatste filmpje.
 
Wouter Hardeman

Wouter Hardeman

15/06/2011 22:05:12
Quote Anchor link
Ik dacht echt dat 16GB genoeg moest zijn voor m'n server... :/

Tevens heb ik al geprobeerd om variables te unsetten, maar zonder succes. Ik krijg een error wanneer ik objects (YouTube API werkt met objects) in een session probeer te zetten. Ook met serialize()
Gewijzigd op 15/06/2011 22:11:42 door Wouter Hardeman
 
Jelmer rrrr

Jelmer rrrr

15/06/2011 22:29:35
Quote Anchor link
Zou je wat code kunnen posten? Niet alles, maar ongeveer dat waarin globaal staat wat je doet (het ophalen, het verwerken, het opslaan)

Ik denk dat je daar een heleboel kan verbeteren, want in principe heb je hiervoor amper geheugen nodig: gewoon één filmpje per keer verwerken, dan hoef je altijd maar data voor één filmpje in het geheugen te houden. En aangezien PHP toch niet threaded is en ik niet aanneem dat je ingewikkelde dingen met curl aan het doen bent, denk ik dat dat prima mogelijk is.
 
Wouter Hardeman

Wouter Hardeman

15/06/2011 23:07:39
Quote Anchor link
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
function printEntireFeed($videoFeed, $counter) {
    mysql_connect("", "", "");
    mysql_select_db("");
 foreach($videoFeed as $videoEntry) {
     $videoThumbnails = $videoEntry->getVideoThumbnails();
     foreach($videoThumbnails as $videoThumbnail) {
        $thumbnails[] = $videoThumbnail['url'];
     }
     $query = "INSERT INTO videos (video_id, title, added, updated, private, description, tags, category, viewcount, rating, watch_page_url, flash_url, mobile_rtsp_url, thumbnails) VALUES ('" . $videoEntry->getVideoId() ."', '" . addslashes($videoEntry->getVideoTitle()) . "', '" . $videoEntry->getPublished() . "', '" . $videoEntry->getUpdated() . "', '" . $videoEntry->isVideoPrivate() . "', '" . addslashes($videoEntry->getVideoDescription()) . "', '" . addslashes(implode(", ", $videoEntry->getVideoTags())) . "', '" . $videoEntry->getVideoCategory() . "', '" . $videoEntry->getVideoViewCount() . "', '" . serialize($videoEntry->getVideoRatingInfo()) . "', '" . $videoEntry->getVideoWatchPageUrl() . "', '" . $videoEntry->getFlashPlayerUrl() . "', '" . addslashes(serialize($videoEntry->mediaGroup->content)) . "', '" . serialize($thumbnails) . "')";
     mysql_query($query) or die($query . "<br />" . mysql_error());
     echo $counter . "<br />";
     $counter++;
     unset($videoEntry);
 }

 // See whether we have another set of results
 try {
   $newVideoFeed = $videoFeed->getNextFeed();
   unset($videoFeed);
 } catch (Zend_Gdata_App_Exception $e) {
   echo $e->getMessage() . "<br />\n";
   if($e->getMessage() == "No link to next set of results found.") {
        return;
   } else {
        printEntireFeed($newVideoFeed, $counter);
   }
 }

 if ($newVideoFeed) {
   echo "-- next set of results --<br />\n";
   printEntireFeed($newVideoFeed, $counter);
 }
}


Als iemand weet hoe ik dat kan optimaliseren, hoor ik het graag. :)
Gewijzigd op 15/06/2011 23:10:23 door Wouter Hardeman
 
Karl Karl

Karl Karl

15/06/2011 23:13:41
Quote Anchor link
Zou je misschien eerst niet een beetje leren over ZEND enzo (dat gebruik je?). Je hoeft niet iedere keer opnieuw te connecten met je database. Verder heb je ook geen foutafhandeling op je database (nee, 'or die' is geen foutafhandeling).
 
Wouter Hardeman

Wouter Hardeman

15/06/2011 23:19:10
Quote Anchor link
Nee, ik gebruik de Google Data APIs. Ik gebruik het framework verder niet. http://framework.zend.com/download/gdata

Verder is het geen openbaar script en hoeft de error niet afgehandeld te worden.
 
Jelmer rrrr

Jelmer rrrr

15/06/2011 23:30:34
Quote Anchor link
Als prolog fan vind ik recursie prachtig, maar ik zou het niet gebruiken in PHP: grote kans dat hij variabelen pas vrij geeft aan het eind van een functie, en dat is in pure recursie pas aan het eind het geval. (prolog en andere talen die ervoor gemaakt zijn optimaliseren dat automatisch)

Dus gewoon een while lus. En escape alles! Ook dat wat uit Google's API komt. Niet ervan uit gaan dat het wel veilig is.
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
<?php
// buiten de functie gehaald om er niet voor te zorden dat hij iedere keer
// er nog een verbinding bij maakt.

mysql_connect("", "", "");
mysql_select_db("");

function
escape_date($date)
{

    $time = strtotime($date);
    return date('Y-m-d H:i:s', $time);
}

function
escape_bool($bool)
{

    // Geen idee hoe jij bools in je database opslaat
    return $bool ? 'yes' : 'no';
}

function
import_feed($videoFeed)
{

    $videos_imported = 0;
    
    foreach($videoFeed as $videoEntry)
    {

        $videoThumbnails = $videoEntry->getVideoThumbnails();
        foreach($videoThumbnails as $videoThumbnail) {
            $thumbnails[] = $videoThumbnail['url'];
        }

         
        $query = "
            INSERT INTO videos (
                video_id,
                title,
                added,
                updated,
                private,
                description,
                tags,
                category,
                viewcount,
                rating,
                watch_page_url,
                flash_url,
                mobile_rtsp_url,
                thumbnails
            ) VALUES (
                '"
. mysql_real_escape_string($videoEntry->getVideoId()) ."',
                '"
. mysql_real_escape_string($videoEntry->getVideoTitle()) . "',
                '"
. escape_date($videoEntry->getPublished()) . "',
                '"
. escape_date($videoEntry->getUpdated()) . "',
                '"
. escape_bool($videoEntry->isVideoPrivate())  . "',
                '"
. mysql_real_escape_string($videoEntry->getVideoDescription()) . "',
                '"
. mysql_real_escape_string(implode(", ", $videoEntry->getVideoTags())) . "', -- is dit een goed idee?
                '"
. mysql_real_escape_string($videoEntry->getVideoCategory()) . "',
                "
  . intval($videoEntry->getVideoViewCount()) . ",
                '"
. mysql_real_escape_string(serialize($videoEntry->getVideoRatingInfo())) . "',
                '"
. mysql_real_escape_string($videoEntry->getVideoWatchPageUrl()) . "',
                '"
. mysql_real_escape_string($videoEntry->getFlashPlayerUrl()) . "',
                '"
. mysql_real_escape_string(serialize($videoEntry->mediaGroup->content)) . "',
                '"
. mysql_real_escape_string(serialize($thumbnails)) . "'
            )"
;
            
         if (!mysql_query($query))
        {

            echo mysql_error() . '<br><br><pre>' . $query . '</pre>';
            continue; // probeer volgende video
        }
        
        ++
$videos_imported;
    }

    
    return $videos_imported;
}

function
import_entire_feed($video_feed)
{

    $imported_videos = 0;
    
    while ($video_feed)
    {

        $imported_videos += import_feed($video_feed);
        // geeft NULL terug als er geen volgende feed is zegt de handleiding
        // en dan stopt de WHILE lus.

        $video_feed = $video_feed->getNextFeed();
    }

    
    return $imported_videos;
}


$imported_videos = import_entire_feed($feed);
printf('Imported %d videos', $imported_videos);
?>
 
Wouter Hardeman

Wouter Hardeman

16/06/2011 00:10:41
Quote Anchor link
Als eerste, bedankt! :D Het werkt perfect!

Dit is inderdaad een veel slimmere manier, veel van geleerd.

Maar wat bedoel je met: "is dit een goed idee?"?
 
Jelmer rrrr

Jelmer rrrr

16/06/2011 00:24:03
Quote Anchor link
Als je de categorieën met komma's scheidt kan je er niet zo makkelijk op koppelen als dat je een koppeltabel gebruikt: mysql one to many relation of [http://www.phphulp.nl/php/tutorial/overig/normaliseren/150/]Normaliseren[/url].
 



Overzicht Reageren

Get Adobe Flash player