Les suspects habituels - le profiler, trouver la ligne la plus chère, comprendre ce qu'elle fait, la réparer. Si vous n'avez pas fait beaucoup de profilage auparavant, il se peut que de grosses boucles quadratiques ou des doublons de chaînes se cachent derrière des expressions d'apparence inoffensive.
En Python, deux des causes les plus courantes que j'ai trouvées pour un ralentissement non évident sont la concaténation de chaînes et les générateurs. Puisque les chaînes de caractères de Python sont immuables, faire quelque chose comme ceci :
result = u""
for item in my_list:
result += unicode (item)
copiera le tout le site deux fois par itération. Ce problème a été bien traité, et la solution consiste à utiliser la méthode suivante "".join
:
result = "".join (unicode (item) for item in my_list)
Les générateurs sont un autre coupable. Ils sont très faciles à utiliser et peuvent simplifier énormément certaines tâches, mais un générateur mal appliqué sera beaucoup plus lent que le simple fait d'ajouter des éléments à une liste et de renvoyer cette liste.
Enfin, n'ayez pas peur de réécrire les bits en C ! Python, en tant que langage dynamique de haut niveau, n'est tout simplement pas capable d'égaler la vitesse du C. S'il y a une fonction que vous ne pouvez plus optimiser en Python, envisagez de l'extraire vers un module d'extension.
Ma technique préférée pour cela est de maintenir les versions Python et C d'un module. La version Python est écrite de manière à être aussi claire et évidente que possible - tout bogue doit être facile à diagnostiquer et à corriger. Ecrivez vos tests pour ce module. Ensuite, écrivez la version C, et testez-la. Son comportement devrait dans tous les cas être égal à celui de l'implémentation Python -- s'ils diffèrent, il devrait être très facile de déterminer lequel est mauvais et de corriger le problème.