Lenteur du PHP ?

Petit nouveau ! | 2 Messages

26 oct. 2015, 13:10

Bonjour

Depuis 1 semaine, je me prend la tête à essayer de m'expliquer pourquoi PHP est il si lent pour un script créant un certain nombre de permutations sur un tableau d'entiers, comparé à JavaScript.

Mes scripts sont parfaitement rodés, optimisés etc... (J'utilise un seul tableau dont je modifie l'ordre des index).

Je suis parti du script javascript que j'ai adapté au PHP.

Résultats, pour JavaScript, un tableau de 12 élements (479 001 600 permutations):
- environ 14s sous Chromium
- environ 69 s sous opera (déjà 4 fois plus lent)
- autre navigateurs (Firefox, Qupzilla), messages d'alertes...

Résultats pour JavaScript pour un tableau de 10 éléments (3 628 800 permutations):
- 0.11 s sous chromium
- 0.48s sous Opera
- 0.16s pour seamonkey
- 0.54s pour qupzilla
- 0.16s pour firefox

Résultat pour le même nombre d'élément (10) avec les 3 628 800 en PHP (mode console, c'est à dire en tapant "php myscript.php"):
13 secondes!

Soit un temps d'exécution au mieux x26 comparé à JavaScript, et au pire X100! (Et je ne parle pas du temps que ça aurait mis avec 11 éléments, où on est à 136s).

Pourquoi cette lenteur ? Il me semblait que le moteur Zend faisait une compilation du script à la volée et que le code devait donc être "rapide", or ce n'est pas le cas.

J'ai eu beau chercher un moyen de voir s'il n'y avait pas des directives qui pourraient améliorer le temps d'exécution, mais en fait il n'y a rien! Le code n'utilise que peu de mémoire (un seul tableau de 10 ou 12 éléments) et si j'enlève la partie tri sélection (nécessaire pour les permutations), le temps est juste divisé par 2. Je précise qu'en mode serveur Apache, les temps d'exécution sont du même ordre.

Alors j'ai lu quelque part que PHP 7 était largement optimisé au niveau des vitesses d'exécution, je pense que c'est pas un luxe au vie de ces résultats.

Ma question est donc, y-a-t-il un moyen d'améliorer les performances de PHP pour diviser le temps d'exécution au moins par 5 ?

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 9782 Messages

26 oct. 2015, 14:56

Bonjour,

Difficile de te répondre sans connaitre ni ton script ni la config de ton serveur Apache/PHP et la config de machine sur laquelle ça tourne.
Quand tout le reste a échoué, lisez le mode d'emploi...

Petit nouveau ! | 2 Messages

26 oct. 2015, 18:36

Bonjour

Je viens d'installer OpenSuse 13.1 (j'avais la 12.3 auparavant) et la version de PHP est passée de 5.3 à 5.4 et en relançant le test, j'ai déjà un gain d'au moins 25 à 30 %! (C'est à dire que pour 10 élément, ça passe sous les 10s (9 s) et pour 11, ça passe de 134 à 100 secondes. Au vue de ce que j'ai lu pour la version 5.6 et surtout la version 7 de PHP... Je pense qu'on devrait avoir des temps assez proche des interpréteurs JS (au moins des plus lent comme celui de qupzilla par exemple). et c'est plutôt rassurant (En ce moment, il y a node.js qui commence à faire parler de lui, même si sa vitesse est phénoménale - puisque c'est du JS - il n'en demeure pas moins qu'il est très compliqué à programmer et qu'il manque moult chose pour arriver au niveau de PHP)

Les scripts ne sont pas en cause, j'ai utilisé des variables tableau par référence mais si ça vous intéresse, je le met (sachant que l'algorithme de permutation est une création personnelle qui ne semble pas exister sur le net! Les algo trouvés sur le net se contente de la récursivité en copiant le contenu du tableau dans un nouvel espace mémoire... ce qui plante au delà d'un certain nombre d'éléments dans la liste - problème mémoire). J'ai donc créé un algo qui n'utilise qu'un seul tableau pour l'ensemble des opérations (récursivement). Ca oblige également à faire un tri quand on arrive en fin de permutation à une étape pour le ième élément.
[code]function tri_selection(&$tableau, $debut, $fin)
	{
	for ($i=$debut; $i<$fin; $i++)
		{
		$id_minimum = $i;
		$tampon = $tableau[$i];
		for ($j=$i+1;$j<$fin;$j++)
			{
			if ($tableau[$j]<$tampon)
				{
				$id_minimum = $j;
				$tampon = $tableau[$id_minimum];
				}
			}
		$tableau[$id_minimum]=$tableau[$i];
		$tableau[$i] = $tampon;
		}
	}

function permutation($position)
	{
/*
*/
	global $taille_ori, $liste3_var;
	for ($i=$position+1;$i<$taille_ori;$i++)
		{
		if ($taille_ori-$position>2)
			permutation($position+1);
		$tempo=$liste3_var[$i];
		$liste3_var[$i]=$liste3_var[$position];
		$liste3_var[$position] = $tempo;
		action_permutation2();
//		if ($i == $taille_ori-1)
		}
	if ($taille_ori-$position>2)
		permutation($position+1);
	tri_selection($liste3_var, $position, $taille_ori);
	}

$nb_permutations=0;
for($i=0;$i<11;$i++)
	{
	$liste_var[$i]=$i;
	}
$liste3_var = $liste_var;
$taille_ori = count($liste_var);

$debut = time();
permutation(0);
echo ("résultat ".$nb_permutations." en ".(time()-$debut)." s.");[/code]

ViPHP
ViPHP | 928 Messages

28 oct. 2015, 01:18

Tu peux utiliser un profiler pour essayer de voir quelles parties de ton script sont lentes. Les performances de PHP sont globalement meilleures avec le temps, mais dans tous les cas ce n'est pas un langage qui est fait pour ce type d'algorithmes. Pour faire des opérations de bas niveau mieux vaut utiliser un langage de bas niveau.