LSL Script Efficiency/fr

From Second Life Wiki
< LSL Script Efficiency
Revision as of 02:13, 4 December 2007 by Jeff Kelley (talk | contribs) (first translation)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

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 odre 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 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 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, or 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).

Quel 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 HUD. Elles sont la moyenne de 20 exécutions.

  ++a:     0.173780 ms    std. dev.:  0.003393 ms
  a += 1:  0.181720 ms    std. dev.:  0.013267 ms
  a++:     0.243500 ms    std. dev.:  0.013816 ms

a++ prend en gros 40% de temps de plus que ++a.

Bien que ces données soient correctes, elles n'ontas é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 millis
  a += 1:  0.346900 millis
  a++:     0.413700 millis

Même test pour la boucle for:

  ++a:     0.358370 millis
  a += 1:  0.351200 millis
  a++:     0.424600 millis

llOwnerSay v. llSay v. llShout v. llWhisper (canal 0):

  llOwnerSay(): 4.359000 millis
  llWhisper():  5.201000 millis
  llSay():      5.226000 millis
  llShout():   14.877000 millis

Autres canaux (llSay() Used for all):

  -100000000: 1.226400 millis
  -100000:    1.254300 millis
  -100:       1.296100 millis
  -1:         1.292400 millis
  0:          5.226000 millis
  1:          1.242300 millis
  100:        1.249100 millis
  100000:     1.219700 millis
  100000000:  1.228700 millis

Longueur du texte (llSay() et canal 1:

   1 Character:    1.242300 millis
   10 Characters:  1.309700 millis
   100 Characters: 1.965600 millis