28-05-2009, 12:46 PM
Voici la solution que j'ai apportée au problème.
Souhaitant éviter de charger le PHP avec trop de boucles et de tests, je me suis orienté vers une solution tout SQL.
J'ai cherché un moyen me permettant de mettre à jour toute la table des PNJs en une seule passe tout en évitant les requêtes imbriquées et les syntaxes trop lourdes (bourrées de IF, RAND et autre fonctions).
Finalement, j'ai décidé de m'appuyer sur une table que je qualifierai de 'modèle de progression'
J'ai une procédure qui tire à l'avance l'évolution des caractéristiques et la range dans une table.
Ces évolutions sont regroupées par 'modèle'.
La structure de la table est la suivante
Lorsqu'un PNJ est créé, je lui affecte au hasard un profil (j'en ai 1000 différents par race).
Ces informations sont stockées avec les informations du PNJ.
Quand vient l'heure de faire évoluer les besoins, une simple requête avec un join me permet de mettre à jour tous les personnages en même temps.
Comme je l'ai noté plus haut, cette méthode me permet de faire évoluer 250.000 PNJs d'un coup en quelques secondes.
Sur ma machine locale, la moyenne est de 4.5 secondes
En passant la table des Modèles en type MEMORY, je descends à 3.6 (comme quoi, les formats de table influent énormément. En MyISAM sur la table modèle, ça monte à 18s de traitement...)
Vous remarquerez que j'utilise un RAND() dans la procédure de mise à jour.
Cela me permet de changer les profils en réassignant un N° de modèle à chaque tour.
J'ai testé diverses méthodes
- actualiser le profil via une 2e requête
- régénérer une nouvelle table de modèles
- utiliser un IF avec un offset pour réassigner un nouveau N°)
Au final, le RAND est la méthode qui en moyenne semble le plus efficace.
Souhaitant éviter de charger le PHP avec trop de boucles et de tests, je me suis orienté vers une solution tout SQL.
J'ai cherché un moyen me permettant de mettre à jour toute la table des PNJs en une seule passe tout en évitant les requêtes imbriquées et les syntaxes trop lourdes (bourrées de IF, RAND et autre fonctions).
Finalement, j'ai décidé de m'appuyer sur une table que je qualifierai de 'modèle de progression'
J'ai une procédure qui tire à l'avance l'évolution des caractéristiques et la range dans une table.
Ces évolutions sont regroupées par 'modèle'.
La structure de la table est la suivante
Code :
Race | Ref | Faim |Hygiène| Santé | Repos | Loisir| Zen |
--------|--------|-------|-------|-------|-------|-------|-----|
Astyrion| 1 | 4 | 1 | 2 | 4 | 3 | 1 |
Astyrion| 2 | 1 | 2 | 4 | 3 | 1 | 2 |
Astyrion| 3 | 3 | 5 | 2 | 4 | 2 | 3 |
...
Bellist | 1 | 1 | 3 | 4 | 3 | 4 | 3 |
Bellist | 2 | 1 | 1 | 1 | 5 | 1 | 3 |
Bellist | 3 | 3 | 1 | 3 | 3 | 2 | 1 |
...
Lorsqu'un PNJ est créé, je lui affecte au hasard un profil (j'en ai 1000 différents par race).
Ces informations sont stockées avec les informations du PNJ.
Quand vient l'heure de faire évoluer les besoins, une simple requête avec un join me permet de mettre à jour tous les personnages en même temps.
Code :
UPDATE pnj p
INNER JOIN modele m ON
p.race=m.race AND p.ref=m.ref
SET
r.ref=FLOOR(RAND()*1000)+1,
p.faim = p.faim + m.faim,
p.hygi = p.hygi + m.hygi,
p.sant = p.sant + m.faim,
p.repo = p.repo + m.repo,
p.lois = p.lois + m.lois,
p.zen = p.zen + m.zen
Comme je l'ai noté plus haut, cette méthode me permet de faire évoluer 250.000 PNJs d'un coup en quelques secondes.
Sur ma machine locale, la moyenne est de 4.5 secondes
En passant la table des Modèles en type MEMORY, je descends à 3.6 (comme quoi, les formats de table influent énormément. En MyISAM sur la table modèle, ça monte à 18s de traitement...)
Vous remarquerez que j'utilise un RAND() dans la procédure de mise à jour.
Cela me permet de changer les profils en réassignant un N° de modèle à chaque tour.
J'ai testé diverses méthodes
- actualiser le profil via une 2e requête
- régénérer une nouvelle table de modèles
- utiliser un IF avec un offset pour réassigner un nouveau N°)
Au final, le RAND est la méthode qui en moyenne semble le plus efficace.
Quand on te dit qu'un projet est terminé à 90%, prépare toi pour les 90% suivant
Ninety-Ninety Rule
"Une guerre de religions, c'est quand deux peuples s'entretuent pour savoir qui a le meilleur ami imaginaire"
Vu sur IRC
Ninety-Ninety Rule
"Une guerre de religions, c'est quand deux peuples s'entretuent pour savoir qui a le meilleur ami imaginaire"
Vu sur IRC