web-dev-qa-db-fra.com

PHP performances de la baie

Je teste un algorithme pour le remplissage de bacs en 2D et j'ai choisi PHP pour le simuler, car il s'agit de mon langage habituel.

Comme vous pouvez le voir sur http://themworks.com/pack_v0.2/oopack.php?ol=1 cela fonctionne plutôt bien, mais vous devez attendre environ 10 à 20 secondes pour que 100 rectangles soient emballés. Pour certains ensembles difficiles à manipuler, il atteindrait la limite d'exécution de 30 php.

J'ai fait du profilage et cela montre que la plupart du temps, mon script parcourt différentes parties d'un petit tableau 2D contenant des 0 et des 1. Il vérifie si certaines cellules sont égales à 0/1 ou les définit à 0/1. Il peut effectuer de telles opérations des millions de fois et, à chaque fois, cela prend quelques microsecondes.

Je suppose que je pourrais utiliser un tableau de booléens dans un langage à typage statique et que les choses iraient plus vite. Ou même faire un tableau de valeurs 1 bit. Je pense convertir le tout en un langage compilé. Est-ce que PHP n'est pas bon pour ça?

Si j'ai besoin de le convertir en disons C++, quelle est la qualité des convertisseurs automatiques? Mon script est juste un tas de boucles for avec des tableaux de base et des manipulations d'objets.

Modifier. Cette fonction est appelée plus que toute autre. Il lit peu de propriétés d'un objet très simple et passe en revue une très petite partie d'un petit tableau pour vérifier s'il existe un élément différent de 0.

function fits($bin, $w, $h, $x, $y) {

    $w += $x;
    $h += $y;

    for ($i = $x; $i < $w; $i++) {

        for ($j = $y; $j < $h; $j++) {

            if ($bin[$i][$j] !== 0) {
                return false;
            }
        }
    }

    return true;    
}

Mise à jour: j'ai essayé d'utiliser 1d array au lieu de 2d comme l'une des réponses suggérées. Comme j'avais toujours besoin d'avoir toujours la largeur actuelle des bacs, j'ai décidé de tout envelopper dans l'objet. De plus, dans chaque boucle, l'index doit être calculé. Maintenant, le script prend encore plus de temps à exécuter. D'autres techniques n'amélioraient pas beaucoup les performances mais rendaient le code moins lisible. C'est l'heure du hip hop, je suppose.

Mise à jour: depuis que hiphop php ne fonctionne que sur linux, et je n'en ai pas, j'ai décidé de réécrire le tout en C++. C'est agréable de rafraîchir les anciennes compétences. De plus, si je trouve un moyen d'utiliser hiphop, il sera intéressant de comparer le code C++ écrit à la main et celui que générerait hiphop.

Mise à jour: J'ai réécrit cette chose en c ++. En moyenne, cela fonctionne 20 fois plus vite et utilise beaucoup moins de mémoire. Laissez-moi voir si je peux le faire encore plus vite.

33
Ivan Vashchenko

L'accès aux tableaux dans PHP peut certainement être lent. PHP utilise des tables de hachage pour implémenter des tableaux, c'est-à-dire que pour accéder à un élément d'un tableau, il doit calculer un hachage et parcourir une liste chaînée. L'utilisation d'un langage compilé avec de véritables baies améliorera certainement les performances, car un accès direct à la mémoire est créé. Pour les intéressés: Code pour accès par hachage avec chaîne et avec entier .

En ce qui concerne votre code, il y a plusieurs points que je voudrais optimiser:

  • return directement, ne pas break deux fois.
  • mettre $file->get_width() et $file->get_height dans des variables simples. Je suppose que la hauteur ou la largeur ne change pas tout au long du processus. Rappelez-vous: les fonctions dans PHP sont lentes.
  • Utilisez un tableau unidimensionnel au lieu des tableaux imbriqués. Vous enregistrez ainsi une recherche de hachage par itération. En réalité, un tableau unidimensionnel n’est que marginalement plus rapide, voire légèrement plus lent. Comparaison de plusieurs façons de sauvegarder les données concernant les performances et l’utilisation de la mémoire .

.

function fits($bin, $x, $y, $w, $h) {
    $w += $x;
    $h += $y;

    for ($i = $x; $i < $w; ++$i) {
        for ($j = $y; $j < $h; ++$j) {
            if ($bin[$i][$j] !== 0) {
                return false;
            }
        } 
    }

    return true;   
}

Bien que je ne sois pas sûr de savoir pourquoi vous ajoutez $x au $width/$y au $height. Ne voulez-vous pas parcourir les coordonnées actuelles jusqu'aux limites de l'image?

21
NikiC

La solution à votre problème pourrait être https://github.com/facebook/hiphop-php/wiki/

Comme chacun l’a dit, PHP n’est pas le langage optimal pour les tâches de calcul intensif. De plus, il n’a pas vraiment de type tableau. Ce qui est décrit comme array() dans PHP est en réalité une carte dictionnaire/hash. Il a quelques optimisations à doubler en tant que liste, mais comme vous l'avez déjà découvert, il ne fournit pas le même comportement à l'exécution que les pointeurs et les tableaux C.

HipHop peut transformer le code PHP en C++ optimisé. Il était également ciblé sur la manipulation de chaîne, mais il pourrait très bien offrir une transformation appropriée tableau/liste.

Disclaimer: Je n'ai jamais essayé. Je voulais juste contribuer ici à une réponse intelligente.

11
mario

Pour suggérer une autre alternative PHP:

Avez-vous examiné SplFixedArray ?

En fonction de la structure de vos tableaux (linéaires de 0 à x), cela peut être un peu plus rapide.

Pour un repère, voir: http://www.slideshare.net/tobias382/new-spl-features-in-php-53 Diapositives 15 et 16 (désolé, je n’en ai pas trouvé un meilleur)

6
edorian

RÉPONSE MISE À JOUR NÉCESSAIRE EN 2018.

Cette question est ancienne et les réponses données ne sont pas tout à fait vraies dans PHP 7 _ {if _ vous utilisez des tableaux compactés. Parce que la question apparaît en premier sur Google, j'ajoute une nouvelle réponse

Si vous utilisez uniquement des entiers en tant que clés de tableau dans PHP 7 et assurez-vous de les insérer dans le tableau dans l'ordre croissant, vous pouvez constater des améliorations 10 fois plus rapides. 

Lire ici: Blackfire Blog sur PHP 7 Améliorations de tableaux

4
JamesHoux

Une alternative plus récente est l'extension QB de PHP spécialement conçue pour résoudre ce type de problème.

Alors que PHP est un excellent langage pour la construction de sites Web complexes application, il impose certaines limitations. Écrire un code qui effectue des tâches de bas niveau et de calcul intensif dans PHP est généralement peu pratique - ce serait tout simplement trop lent. L'extension QB résout cette faiblesse particulière de PHP. En traduisant les opcodes Zend et les exécuter via une machine virtuelle à typage statique, QB offre un gain de performance en ordre de grandeur. Le pouvoir supplémentaire permet à PHP les programmeurs de faire des choses qu'ils étaient incapables de faire auparavant, comme. manipulation d'image complexe au niveau des pixels.

Voir: http://php-qb.net/

1
Treffynnon

Les tableaux dans PHP semblent en effet être assez lents, en particulier lors de la lecture en boucle de tableaux multidimensionnels. Une autre option serait d’essayer Quercus . C'est une implémentation de PHP en Java. Je suppose qu'il utilise des tableaux Java. Je n'ai pas fait de comparaison cependant.

0
Erik B