[PHP] Code optimaliseren

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Vold
  • Registratie: September 2001
  • Laatst online: 22-01 23:04
Hallo,

Ik heb voor mijn site (zie ondertitel) een redelijk zwaar script draaien, het haalt van ongeveer 70 verschillende site's de feeds op, zet dat om in nuttige dingen, kijkt of het al in de database voorkomt, en zo niet voegt het dan toe. Nu vond ik het al een wonder dat mij dit is gelukt om te maken, maar dit script is wel enorm traag kwam ik laatst achter :X (parsetijden van+60sec.). Nu wordt dit script d.m.v een cronjob elk kwartier uitgevoerd, dus een echte ramp is het niet, maar als er meer feeds bijkomen is dit toch erg vervelend op de lange duur.

Ideeën die ik zelf al heb:
- Ik controleer eigenlijk bij elk artikel of de link niet al in de database voorkomt, maar ik heb het veld "link" ook al de waarde "UNIQUE" meegeven.. Dan zou ik de controle toch kunnen weglaten ? Of moet je de fouten dan afvangen oid ?
- Sommige feeds van site's zijn soms niet bereikbaar, dan gaat hij wachten totdat er een timout komt (denk ik), is dit op een of andere manier af te vangen ?
- Verder is mn code in zn algemeen prut, maar hier komt gebrek aan ervaring en kennis om de hoek kijken, en dat los je niet zo heel snel op. :P

Dat was het wel dacht ik zo, als iemand vragen heeft ben ik natuurlijk altijd bereidt om wat meer uitleg te geven :)

Ohja de code zelf, zou ik toch bijna vergeten:
PHP:
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
<?php
$sStart = microtime(); 
//verbinding maken
$dbh=mysql_connect ("localhost", "loginnaam", "wachtwoord") or die ('I cannot connect to the database because: ' . mysql_error());
mysql_select_db ("metspek_rss");
// Haal feed gegevens uit de database
$feed_sql = mysql_query("SELECT feed_id,url FROM feeds WHERE ondersteuning='1'");
if (!$feed_sql) {
   echo 'Could not run query: ' . mysql_error();
   exit;
}
//begin de feeds langs te lopen
while($feed = mysql_fetch_array($feed_sql)) {
$data = "";
$rss = "";

    // Haalt het RSS-file op en zet deze in een variabele
    if($file = fopen($feed['url'],"r"))
    {
        while(!feof($file))
        {
            $data .= fgets($file, 1024);
        }
        fclose($file);
    }

    // Zet de RSS-feed in een array
    $p = explode("<item>", $data);
    for($i = 0; $i < count($p); $i++)
    {
        $item = $p[$i];
        if($q = stristr($item, "<title"))
        {
            $r = stristr($q, "</title");
            $rss[$i]['title'] = substr($q, 7, strlen($q) - strlen($r) - 7);
            $rss[$i]['title'] = html_entity_decode($rss[$i]['title']);
            $rss[$i]['title'] = str_replace(" ", " ", $rss[$i]['title']);
        }
        if($q = stristr($item, "<pubDate"))
        {
            $r = stristr($q, "</pubDate");
            $rss[$i]['pubdate'] = strtotime(substr($q, 9, strlen($q) - strlen($r) - 9));
        }

        if($q = stristr($item, "<link"))
        {
            $r = stristr($q, "</link");
            $rss[$i]['link'] = substr($q, 6, strlen($q) - strlen($r) - 6);
        }
    }
    
    //hier dus het toevoegen controle enzo
    if($rss) {
    for($i = 0; $i < count($rss); $i++)
{
$link = $rss[$i]['link'];
$check = mysql_query("SELECT * FROM links WHERE link='$link'");
$tel = mysql_num_rows($check);
    if($tel == '0') {
        //datum goedzetten
            if($rss[$i]['pubdate']) { $date = date("Y-m-d H:i:s", $rss[$i]['pubdate']); } 
                else { $date = date("Y-m-d H:i:s"); }   
            //toevoegen
                $titel = $rss[$i]['title'];
                $link = $rss[$i]['link'];
                $feed_id =  $feed['feed_id'];
                $link_sql = mysql_query("INSERT INTO links (titel,link,datum,feed_id) VALUES ('$titel','$link','$date','$feed_id')"); 
        } //einde tel
} //einde forlus controleren en toevoegen rssfeed
}//einde rss wel waarde
} //einde whilelus voor feed gegevens
// Statistieken maken..
$query = mysql_query("SELECT * FROM links");
$aantallinks = mysql_num_rows($query);
$datum = date("Y-m-d H:i:s");
if(substr(date("i"), 0, 1) == '0') {
if(date("H") == '00') { $dag = '1'; } else { $dag = '0'; }
mysql_query("INSERT INTO linkstatistieken (aantallinks,datum,dag) VALUES ('$aantallinks','$datum','$dag')"); 
}
$sEnd = microtime();
$aA = explode(' ',$sStart.' '.$sEnd);
$tijd = round(($aA[2]+$aA[3])-($aA[0]+$aA[1]),8);
echo '- Pagina gegenereerd in ' . $tijd . ' sec.';
?>


De parsetime bij de laatste test was 122 seconde, wie helpt dat te verbeteren ? :+

[ Voor 66% gewijzigd door Vold op 02-01-2005 18:56 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Het ligt denk ik niet aan je host maar meer aan de rss feeds zelf. Deze kunnen soms (als de server waar ze opstaan belast is) traag geladen worden en zo dus jouw script vertragen. Er is niet echt een oplossing hiervoor.

Acties:
  • 0 Henk 'm!

  • MisterData
  • Registratie: September 2001
  • Laatst online: 29-08 20:29
Tsja, als je nou een andere taal had gehad (servlets met Java ofzo) dan had je multithreaded die verbindingen kunnen starten en ze gewoon afwerken op het moment dat er eentje binnen is... de trage hosts vertragen je script dan niet meer :)

Acties:
  • 0 Henk 'm!

  • Vold
  • Registratie: September 2001
  • Laatst online: 22-01 23:04
Mja, ik zit wel aan php vast op dat gebied, het is de enige programmeertaal (op Basic na) die ik redelijk onder de knie heb. Hoe zit het trouwens met dat UNIQUE gebeuren, kan ik ook gewoon domweg alle gegevens er instoppen, want de dubbele waarde worden toch niet toegevoegd ? Of is dat een te ranzige methode ?

Acties:
  • 0 Henk 'm!

  • Koeniepoenie
  • Registratie: Oktober 2003
  • Laatst online: 15-09 21:46
Hm, ik zit wat te kijken, en kun je die while lus waarmee je de RSS feed binnenhaalt niet vervangen door bijv. een functie als file_get_contents(), want dan heb je iig al heel wat lussen minder. En ik denk toch dat het meeste tijd gaat zitten in het puur ophalen van de feeds..

Parse error: syntax error, unexpected GOT_USER in https://gathering.tweakers.net on line 1337


Acties:
  • 0 Henk 'm!

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 29-05 22:54
Ik zie niet zo snel hoe je dit kunt verbeteren. Je zit gewoon vast aan de responsetime van de servers waar je wat van af haalt zoals al gezegd. Doe anders eens een tijd opname om ieder stukje code die je verdacht vindt. Bijvoorbeeld iedere keer in die while lus. Kun je gelijk zien hoe lang dat duurt.

Verder is er ook nog zoiets als Zend Optimizer. Deze cached de geparste code zodat dit heel wat overhead weg laat.

Noushka's Magnificent Dream | Unity


Acties:
  • 0 Henk 'm!

  • Vold
  • Registratie: September 2001
  • Laatst online: 22-01 23:04
Michali schreef op zondag 02 januari 2005 @ 19:21:
Ik zie niet zo snel hoe je dit kunt verbeteren. Je zit gewoon vast aan de responsetime van de servers waar je wat van af haalt zoals al gezegd. Doe anders eens een tijd opname om ieder stukje code die je verdacht vindt. Bijvoorbeeld iedere keer in die while lus. Kun je gelijk zien hoe lang dat duurt.

Verder is er ook nog zoiets als Zend Optimizer. Deze cached de geparste code zodat dit heel wat overhead weg laat.
Mmm okee dat begrijp ik wel.., en jammer genoeg is Zend geen optie omdat ik het neit zelf host.. Maar zou iemand nog even kunnen toelichtingen hoe dat met UNIQUE zit ? ZOu ik die check ook weg kunnen laten ?

Acties:
  • 0 Henk 'm!

Verwijderd

Via Bash kun je je script multi-proces maken. Maar of je nu voor elke RSS feed een apart script wil hebben :?

Je kunt ook uit je script via een andere cronjob, de hierboven beschreven scripts genereren. :X

Iedereen die dit een hack noemt: helemaal mee eens en ik zou het zelf nooit zo doen. Tenzij je zeker bent dat je nooit meer iets wilt veranderen aan je script, maar dat lijkt me onwaarschijnlijk. :Y)

Acties:
  • 0 Henk 'm!

  • Erkens
  • Registratie: December 2001
  • Niet online

Erkens

Fotograaf

MisterData schreef op zondag 02 januari 2005 @ 18:58:
Tsja, als je nou een andere taal had gehad (servlets met Java ofzo) dan had je multithreaded die verbindingen kunnen starten en ze gewoon afwerken op het moment dat er eentje binnen is... de trage hosts vertragen je script dan niet meer :)
waarom zou dat met PHP niet kunnen ;)
zeker aangezien dit script dus via de shell aangeroepen wordt kan je prima andere scripts starten, de output van je script hoeft toch nergens heen :)

Acties:
  • 0 Henk 'm!

  • elevator
  • Registratie: December 2001
  • Niet online

elevator

Officieel moto fan :)

Mocht je gebruik maken van PHP5 zou je eens kunnen kijken naar http://nl2.php.net/manual/en/function.curl-multi-exec.php om op die manier iets aan tijd te winnen (mits je bandbreedte genoeg hebt) :)

Acties:
  • 0 Henk 'm!

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

(jarig!)
Zorg er voor dat je op zijn minst de parse-tijden per geopende site weet en het liefst nog wat specifieker dan dat, ipv alleen de totaal. Veel optimalisatie aan de code zal er wel niet mogelijk zijn als blijkt dat alle tijd gaat in het wachten op de externe hosts.
Als blijkt dat het gros van de tijd in die database-calls zit is er nog wel wat aan te doen.

Zaken als het minimaliseren van je call-overhead, het gebruiken van ZendAccelerator en het minimalistisch verbeteren van je code heeft op beide aspecten over het algemeen heel weinig nut en is ook doorgaans nauwelijks effectief om de executietijd van een dergelijk script significant terug te brengen.

Je zou het trouwens ook in 1 script in php zodanig kunnen maken dat je meerdere sites (dmv de streams uit php4.3.x tegelijk uitleest. Simpelweg door naar een aantal (5 ofzo) sites tegelijk een non-blocking stream te openen en dmv de stream_select-functie van php te kijken of je al nieuwe gegevens van de streams hebt. Ben je klaar met die streams, dan open je een nieuwe (al dan niet per batch een serie nieuwe openen, of juist per losse stream).
Waarschijnlijk is het echter makkelijker om losse scripts ervoor te gebruiken. Wel een minder grote uitdaging. ;)

Acties:
  • 0 Henk 'm!

Verwijderd

Het lijkt me,zoals ACM al zegt, zinvol om delen van je script te timen, zodat je precies weet waar de vertragingen zitten en wat dus zinvol is om te optimaliseren.

[ Voor 3% gewijzigd door Verwijderd op 03-01-2005 09:53 . Reden: typo ]


Acties:
  • 0 Henk 'm!

  • ggvw
  • Registratie: September 2001
  • Laatst online: 15-12-2024
Voor het inlezen van de rss feed kan je misschien beter de ingebouwde functie van php gebruiken als je PHP5 geinstalleerd hebt. Misschien is zoiets sneller en eenvoudiger:

code:
1
2
3
4
5
6
7
8
9
10
$nfos = simplexml_load_file('http://www.nforce.nl/rss/rss_all.xml');
foreach($nfos as $zooi)
{
   foreach($zooi as $key=>$items)
   {
        $title = $items->title;
        $link = $items->link;
         //etc...
   }
}


edit:

De meeste tijd gaat, zoals gezegd, waarschijnlijk zitten in het ophalen en inlezen van de rss.
Dit kan je misschien oplossen door via een cronjob op gezette tijden de rss lokaal naar je server toe te trekken, en vanaf lokaal in te lezen; al 'verschuif' je hiermee wel het probleem.

Het is misschien handig om wat meer functies in je code te maken. Dit is niet alleen overzichtelijker maar het maakt dat je over een jaar je code beter begrijpt. Zet bij elke functie een 'timer' die weergeeft hoe lang de functie heeft geduurt. Dan weet je precies waar het meeste tijd in gaat zitten.

[ Voor 44% gewijzigd door ggvw op 03-01-2005 10:24 ]

Pagina: 1