Lenteur de traitement d'une boucle

Petit nouveau ! | 2 Messages

06 juil. 2007, 12:18

Salut à tous,

Débutant en PHP, je viens d'installer un site qui affiche un tableau de résultats tirés de données lues sur un socket réseau local (IP 127.0.0.1), ça fonctionne mais très très lentement alors que le serveur est un monstre qui ne fait rien d'autre.
J'utilise PHP 5.
Voici la partie du script qui me pose problème :

Code : Tout sélectionner

while(TRUE) { $Buffer = ""; $Buffer = fread($Sock,8192); if ( $Buffer == "" ) break; $reponse .= $Buffer; if ( strstr($Buffer,"^^^\r\n") != FALSE ) // Séquence de fin d'envoi break; }
Les données retournées sont à peu près 10000 valeurs dans un tableau qui s'affiche au bout de ... 25 secondes ! En PHP4 j'ai la même chose en 10 secondes, ce qui est tout de même très long.
Je cherche en vain comment optimiser ce script en PHP 5 et suis preneur de toute idée :-)
@+

Eléphanteau du PHP | 39 Messages

06 juil. 2007, 19:32

bonjour netspirit,

Premièrement ton buffer de lecture trop élevé.
Ensuite ton test

Code : Tout sélectionner

strstr($Buffer,"^^^\r\n") != FALSE
n'est pas correcte car si tu veux tester un booléen (etat TRUE ou FALSE) il te faut utiliser l'expression === ou !== (pour strictement égale).

Et pour finir et je pense que ton problème vient de là, tu recherches la chaine suivante "^^^\r\n" depuis ton buffer $buffer et non depuis ta chaine complète $reponse.

Imagine que ta chaine de fin de fichier (ici ^^^\r\n) se retrouve scinder en deux partie. Si ton buffer se remplit juste au moment où ta chaine de fin de donnée arrive et qu'il ne prend que la partie suivante ^^^\ ta détection ne fonctionnera pas.
Tu dois effectuer ton test de recherche sur ta chaine complète (ici $reponse) et non sur ton buffer de réception

Voiçi un exemple de code :

Code : Tout sélectionner

$fd = fopen("http://www.php.net",'r'); do { $buffer = fread($fd,10); $my_string .= $buffer; } while(false === strstr($my_string,"</title>")); echo $my_string;

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

06 juil. 2007, 23:56

En fait, je pense que le plus important serait d'expliquer précisément ce qu'est sensé faire cette boucle (notamment, le format des données et quand, comment et pourquoi ce "^^^\r\n" apparaît).

Pour le reste, personnellement je suis plutôt d'accord avec le fait d'utiliser un "gros" tampon (8 KiB c'est pas non plus énorme) et surtout le fait d'effectuer le test sur le buffer plutôt que la réponse complète, parce que la taille de la réponse augmente en permanence et chaque exécution deviendrait plus longue.

À part ça, je pense qu'il y a eu confusion dans les fonctions à utiliser, et que la solution contiendra plutôt fgets() pour la lecture et un simple substr() pour le test. (le serveur ne ferme-t'il pas la connexion après l'envoi des données ?) Mais pour ça il faudrait connaître le format des données.

Invité
Invité n'ayant pas de compte PHPfrance

07 juil. 2007, 10:46

Oui en effet il serait logique que le serveur ferme la connexion une fois le flux de donnée envoyé auquel cas un simple
while(!feof($Sock))
$reponse .= fgets($Sock,8192);
devrait suffire.

Peut être cherches-tu à récupèrer qu'une partie du flux ?

Petit nouveau ! | 2 Messages

11 juil. 2007, 19:59

Bonsoir à tous,

Désolé pour le retard, nous avons laissé le serveur en prod en PHP4 et les usagers se "contentent" du temps de réponse de 10 secondes.
Je ne suis pas le créateur du script, seulement un admin. Le dév devrait passer par là ou au moins me donner plus d'infos de manière à ce que je puisse vous répondre (type de données, but exact de cette boucle).
Je peux déjà vous dire que le serveur 127.0.0.1 ferme la connexion en moins de deux secondes. Les 6 à 8 secondes suivantes sont consommées par Apache et PHP pour le traitement et la mise en page sous forme d'un tableau de résultats.
@+