2010-04-20 6 views
2

J'ai un script PHP qui va générer un rapport en utilisant PHPExcel à partir de données interrogées à partir d'une base de données MySQL. Actuellement, il est linéaire dans le traitement en ce qu'il récupère les données à partir de MySQL, lit dans le modèle Excel, écrit les données dans le modèle, puis les sort. J'ai optimisé le code au point que les données ne sont répétées qu'une seule fois, et qu'il y a très peu de traitement du côté PHP. La requête renvoie des centaines de lignes en moins de 0,001 seconde, elle s'exécute donc assez rapidement. Après un certain temps, j'ai trouvé mes goulots d'étranglement (surprise, surprise) en lisant le modèle et en écrivant la sortie. Je voudrais faire:Traitement multithread/parallèle en PHP

Spawn a thread/process to read the template 
Spawn a thread/process to fetch the data 
Return back to parent thread - Parent thread will wait until both are complete 
Proceed on as normal 

Mes principales questions sont cela est possible, est-il la peine? Si oui aux deux, comment l'aborderiez-vous? Aussi, il est PHP 5 sur CentOS

Répondre

8

Il est généralement déconseillé d'utiliser un processus Apache. Cela peut entraîner des résultats indéterminés. Au lieu de cela, l'utilisation d'un mécanisme de mise en file d'attente est préférable. Gearman est un mécanisme de mise en file d'attente open source que vous pouvez utiliser. J'ai aussi un billet de blog sur la file d'attente de travail Zend Server qui parle de l'exécution asynchrone des tâches Do you queue? Introduction to the Zend Server Job Queue.

Vous pouvez également utiliser quelque chose comme les classes Zend Framework Queuing pour implémenter une partie du travail asynchrone. Zend_Queue

@Swisstack, aussi je ne suis pas d'accord avec votre affirmation que PHP n'est pas créé pour des performances élevées. Les caractéristiques linguistiques sont rarement la cause de la lenteur des performances. Peut-être qu'en faisant un test de langage brut comparant $ a ++ entre différentes langues, vous le verrez, mais ce type de test n'est pas pertinent. J'ai fait du consulting sur PHP depuis plusieurs années et je n'ai jamais vu de problème de performance dû à la langue.

+0

+1 Bon à mentionner. Je suppose qu'il ne l'exécute pas via un serveur Web. – webbiedave

+0

Eh bien, on ne peut pas en supposer trop. Mais même ainsi, une file d'attente d'emploi est généralement une meilleure route à suivre. C'est plus gérable et comme ça. –

1

Je voudrais essayer de savoir si vous pouvez mettre en cache ou stocker le modèle dans un format plus rapide à lire. Je ne sais pas si c'est possible, mais le forum PHPExcel est plutôt bon et est regardé par les développeurs.

0

Vous pouvez certainement générer des processus sur CentOS avec PHP (http://php.net/manual/en/function.pcntl-fork.php). Avant de faire cela, je considérerais au moins une chose ... Si le goulot d'étranglement semble être à la lecture du modèle et à l'écriture de la sortie, il peut s'agir d'un problème lié aux E/S seulement. ... Personnellement j'essaierais de voir s'il est possible de faire de la mise en cache à la place ...

1

Vous ne pouvez pas multithread mais vous pouvez fork (pcntl_fork, pcntl_wait). Comme je suis sûr, vous voudrez tester soigneusement les temps de réapparition du processus pour vous assurer que cela en vaut la peine pour votre situation.

$pid = pcntl_fork(); 

if ($pid == -1) { 
    // fork failed 

} elseif ($pid > 0) { 
    // we're the parent! Wait for child to finish 
    pcntl_waitpid($pid); 

} else { 
    // we're the child 
} 
1

Si les deux lisant le modèle, et la requête db étaient lents, alors je dirais qu'il y a une chance décente que des performances intéressantes puissent être obtenues en exécutant les tâches en parallèle. Mais, vous l'avez dit vous-même, la lecture du modèle est lente, et la requête db est rapide. Ainsi, même en ignorant tout surcoût supplémentaire créé par les ajouts nécessaires pour exécuter les tâches en parallèle, dans le meilleur des cas, vous économiserez 0,001 secondes (le temps nécessaire pour la requête db).

L'exécution de plusieurs tâches en parallèle nécessite toujours l'heure de la tâche la plus lente. L'exécution de tâches en série est la somme de toutes les tâches. Dans votre cas, templateTime + queryTime (0.001)

Cela ne vaut pas le coup.

Habituellement, la base de données est la tortue dans l'équation. Vous pouvez faire cette partie async sans trop d'effort.Voir les fonctions mysqli_poll() et friend nouvellement ajoutées.

0

Lire le modèle une fois, puis faire un clone pour chaque classeur que vous devez créer à partir des données

+0

Hey Mark, est-ce que vous êtes arrivé à un lien hava à un exemple? ce sera très apprécié! Merci! – mongotop