LSL Script Efficiency/fr
LSL Portail Francophone | LSL Portail Anglophone | Fonctions | Évènements | Types | Operateurs | Constantes | Contrôle d'exécution | Bibliothèque | Tutoriels |
Qu'est-ce que l'efficacité?
L'efficacité est l'inverse des ressources consommées pour effectuer une tâche donnée. Plus le script est efficace, moins il consomme de ressouces. L'efficacité va souvent de pair avec la rapidité, mais cela n'est pas une généralité.
Les points qui ont un impact négatif sur l'efficacité sont, à peu près par ordre d'importance :
- Le nombre de scripts utilisés pour accomplir une même tâche. Cf. Conception Optimale.
- llSleep - Cette fonction consomme 0.2 à 0.3 milliseconde par tranche de temps pendant que le script dort. Les timers (llSetTimerEvent) sont bien plus efficaces.
- Les timers "courts" (< 5 sec) sont grands consommateurs de ressources.
- Listen - particulièrement sur le canal 0
- Les changements fréquents de texture (les autres utilisateurs sont contraints de les charger)
- L'utilisation des rotations côté serveur au lieu de llTargetOmega
- Les gestionnaires d'évènements inutiles (touch, collision, ...)
- Un grand volume de mails ou d'IM
- Les algorithmes non optimaux (recherche linéaire par exemple, par opposition à dichotomie)
- Les boucles d'attente actives
Conception optimale
Chaque script dormant dans un objet ajoute de 0.001 à 0.003 milliseconde par tranche de temps. Moins il y a de scripts, meilleure est l'efficacité.
- Si vous avez besoin d'un tas de "boutons", évitez de mettre un script dans chaque prim. Utilisez llDetectedLinkNumber dans le prim racine pour détecter quel sous-prim a été touché.
- Si vous avez besoin de changer la couleur, la transparence (alpha) ou la texture d'un sous-prim, évitez encore de mettre un script dans chaque prim. Utilisez plutôt llSetLinkAlpha, llSetLinkColor, llSetLinkTexture ou llSetLinkPrimitiveParams.
- Ne mettez jamais un script qui écoute sur le canal 0 (ou autre) dans chaque prim d'un objet complexe . C'est sans doute la pire des choses à faire. Malheureusement, elle est trop fréquente.
- Pensez à utiliser XyzzyText à la place de XyText.
En résumé, si vous êtes sur le point de mettre un script dans chaque prim d'un objet, arrêtez et cherchez comment faire autrement avec moins de scripts. Il existe pratiquement toujours une autre solution. À vous de décider si elle est viable dans le contexte de votre application.
Micro-optimisation
Il existe beaucoup d'astuces pour accélérer les scripts, comme utiliser ++a au lieu de a++. Cependant, ce genre d'optimisations peut se révéler sans effet dans le futur (en cas de changement d'implémentation de LSL).
Combien de temps prend ce code ?
Le code suivant mesure le temps passé dans chaque appel de fonction, en millisecondes.
Atention, ne modifiez pas ce code sur le wiki sans une discussion préalable. Un changement même mineur peut entraîner des discordances dans les mesures. Ce code est un étalon de mesure et doit être recopié exactement, commentaires inclus, tel que figurant ici.
Merci à Xaviar Czervik pour le code original, à Strife Onizuka pour l'amélioration de sa précision, et à tous les autres contributeurs listés dans l'historique de cette page.
//IMPORTANT: Only perform tests in an empty region. // To reduce contamination and be sure to wearing no attachments. // Preferably do tests in a private sim with one on it. // Don't move while performing the test. // There is a margin of error so run the tests multiple times to determine it. integer time() { // count milliseconds since the day began string stamp = llGetTimestamp(); // "YYYY-MM-DDThh:mm:ss.ff..fZ" return (integer) llGetSubString(stamp, 11, 12) * 3600000 + // hh (integer) llGetSubString(stamp, 14, 15) * 60000 + // mm llRound((float)llGetSubString(stamp, 17, -2) * 1000000.0)/1000; // ss.ff..f } default { state_entry() { llOwnerSay((string) llGetFreeMemory()); //test variables float counter; //framework variables float i = 0; float j = 0; float max = 10000; // 2ms of work takes 20 seconds to repeat 10,000 times, plus overhead float t0 = time(); do { //test counter += 1; }while (++i < max); float t1 = time(); do ; while (++j < max); float t2 = time();//remove the time required by the framework float elapsed = ((t1 - t0) - (t2 - t1))/max; llOwnerSay("The function in the loop took a total of " + (string)elapsed + " milliseconds."); } }
Mesures d'efficacité
Les mesures suivantes ont été collectées avec la fonction ci-dessus dans un simulateur récent et vide, avec ce seul script s'exécutant dans un ATH. Elles sont la moyenne de 20 exécutions.
++a : 0,173780 ms dév. std. : 0,003393 ms a += 1 : 0,181720 ms dév. std. : 0,013267 ms a++ : 0,243500 ms dév. std. : 0,013816 ms
a++ prend en gros 40% de temps de plus que ++a.
Bien que les données qui suivent soient correctes, elles n'ont pas été obtenues avec le code de référence ci-dessus, mais avec une version légèrement moins optimisée écrite par Xaviar Czervik. Si quelqu'un pouvait répéter les tests avec la version de référence, merci.
++a : 0,364700 ms a += 1 : 0,346900 ms a++ : 0,413700 ms
Même test pour la boucle for :
++a : 0,358370 ms a += 1 : 0,351200 ms a++ : 0,424600 ms
llOwnerSay par rapport à llSay, llShout еt llWhisper (canal 0) :
llOwnerSay() : 4,359000 ms llWhisper() : 5,201000 ms llSay() : 5,226000 ms llShout() : 14,877000 ms
Autres canaux (llSay() utilisé dans tous les cas) :
-100000000 : 1,226400 ms -100000 : 1,254300 ms -100 : 1,296100 ms -1 : 1,292400 ms 0 : 5,226000 ms 1 : 1,242300 ms 100 : 1,249100 ms 100000 : 1,219700 ms 100000000 : 1,228700 ms
Longueur du texte (llSay() et canal 1) :
1 Caractère : 1.242300 ms 10 Caractères : 1.309700 ms 100 Caractères : 1.965600 ms