août 28

Et les développeurs découvrirent la CRON…

Avec Magento et d’autres frameworks, il devient possible de faire exécuter au site une commande à heure/date/jour fixe par le mécanisme de Cron table. Ce mécanisme, très vieux (au moins 25 ans) et très stable est connu de tous les administrateurs systèmes et réseau, ses excès et débordements occasionnels (si l’on ne fait pas attention au contenu) aussi.

Sauf que quand les développeurs ont mis la mains sur ce petit outil d’automatisation, une nouvelle frontière s’est ouverte en terme de possibilité. Application d’un traitement sur tout le catalogue de nuit, système de calcul des réapprovisionnements, gestions de commandes ou des réductions etc…

Well, le principe est bon alors le partager doit être bon quelque part ?

Mais cela fait maintenant un moment qu’avec l’apparition de PHP, cette question revient :

« Vous pourriez passer la memory limit à 1, 2, 4 Go ? »
Non.

« Mais j’en ai besoin pour mes traitements »
Non.

« Non quoi ? »
Non je ne passerai pas la memory limit à 1,5 Go car vous n’en avez pas besoin.

Pourquoi ?

Déjà parce que l’on a pas besoin de 1 ou 2 ou 4 Go pour effectuer un traitement, aussi volumineux soit-il. Il est *presque* toujours possible de fragmenter le traitement en sous lots plus petits, d’allouer et désallouer sa RAM plus subtilement et d’une manière générale privilégier une méthode de travail moins RAM intensive. (écriture et stockage de résultats partiels, tableaux indexés, traitement par plus petit lots, utilisation de la gestion de mémoire du Zend framework etc…)

Que personne ne tente de s’abriter derrière le *presque*, le nombre des algorithmes complexes non factorisables ou fractionnables est connu et, dans leur très grande majorité, ils touchent aux traitements mathématiques, à la cryptographie ou aux problèmes dits « NP-complets ». Donc NON, il n’est pas impossible de programmer différemment un traitement PHP sur une collection de données, fussent elle grande.

D’ailleurs, la preuve, au final, le développeur contourne le problème et arrive à utiliser une memory limit raisonnable tout en résolvant son problème.

Et pourtant, elle tournait !

Ensuite 1 Go de RAM, c’est beaucoup. Au sens propre.

C’est à dire qu’à une époque pas si lointaine, on chargeait et traitait des collection de données 2 fois moins grandes mais également avec 10 fois moins de RAM. Le catalogue d’une société il y a 10 ans était peut être deux fois moins gros mais peut importe le système utilisé à l’époque, ca tournait et la RAM, à l’époque, il y en avait 10 fois moins et pourtant, ca tournait.

Le coté orgiaque de la progression du matériel et de ses coûts fausse le sens des réalités. Oui un cycle processeur ca compte. Oui une boucle mal optimisée ca joue, surtout multipliée par des milliers de visites. Oui 1 Go de RAM ce n’est pas rien. Selon la configuration de la machine, cela peut même représenter le quart de ses ressources mémoire…

De plus, la memory limit est posée pour tous les processus PHP, pas pour un en particulier. Résultat il est possible qu’un seul script soit gourmand mais rien ne nous certifie que cela ne sera pas le cas d’un autre. Et si 5 ou 6 processus PHP se mettent à consommer 1 Go de RAM, on arrive vite à des sommes qui peuvent mettre des serveurs à mal.

A une époque pas si lointaine sur Amiga et Atari ST, on optimisait jusqu’au moindre octet maintenant c’est une culture perdue, qu’on considère comme dépassée mais sincèrement, cet esprit était le bon. La société de l’hyper consommation nous pousse à manger plus, dépenser plus, imprimer plus et allouer plus de RAM. Ça va avec, le gâchis est devenu une culture. Pourquoi écrire 10 lignes de plus pour avoir une gestion plus rationnelle alors que comme cela ca marche ?

Sans compter que bon nombre de script n’exit jamais et reste en mémoire sans savoir quoi faire, à part bloquer 1 Go de RAM, pour rien.

Quelques bribes de solutions :

Fragmenter le traitement est le plus important, soit dans l’algorithme de traitement, soit dans la gestion de la mémoire.

Quand vous lisez un bouquin, vous le faite page après page et pas les 500 d’un coup, envisageons la même chose pour un serveur.

  1. Prenez la taille de votre traitement, diviser le par 64 ou 128 Mo et vous saurez le nombre de blocs à traiter, le nombre de processus qui devront s’exécuter à la suite pour venir à bout de la tâche. Une fois les résultats calculés, assemblez les au besoins.
  2. Traitez des tableaux ou des indexes qui référencent les données plutôt que toute la donnée en elle même, quand cela est possible.
  3. Utilisez des algorithmes et des clefs de hash pour sotcker et retrouver vos données.
  4. Traitez les données avec le langage le plus adapté. N’oubliez pas que PHP est 10 fois plus lent (au bas mot) que le C pour venir à bout d’un traitement. Sa gestion de la RAM est également moins efficace.
  5. Quand cela est possible, préférez un script SQL à un PHP qui fait du SQL, ca sera considérablement plus rapide et économe en ressources.
  6. Si vous continuer à faire vos Cron en PHP, utilisez Zend_Memory :
    Le composant Zend_Memory est destiné à gérer des données dans un environnement où la mémoire est limitée.
    Les objets mémoire (conteneurs de mémoire) sont produits par le manager de mémoire sur demande et mis en cache/chargés d’une manière transparente quand c’est nécessaire.

    (tiré de la doc ici : http://framework.zend.com/manual/fr/zend.memory.overview.html)
    ah… voila une solution élégante. J’utilise et si je dépasse la RAM allouer, ca swap sur le disque mes résultats intermédiaire.
    (Merci à Samuel Verdier de m’avoir soufflé la solution, il interviendra peut être prochainement sur ce blog pour nous donner des exemples concrets).

écrit par Philippe Humeau \\ tags: , , ,