LSL Script Efficiency/it

From Second Life Wiki
Jump to navigation Jump to search

Cosa si intende con Efficienza

L'efficienza è collegata alla quantità di risorse utilizzate da uno script per ottenere un risultato. Ciò spesso va di pari passo con la velocità di esecuzione, ma non sempre.

Cose da evitare, in un indicativo ordine d'importanza:

  • Utilizzare tanti script per ottenere qualcosa. Confronta Progettazione Efficiente.
  • llSleep - Questa funzione usa fino a 0.2 - 0.3 ms per frame mentre lo script è in attesa, i timer funzionano meglio.
  • Timer a basso periodo (<5 sec)
  • Ascolto - specialmente sul canale 0
  • Modifica frequente delle texture (Altri le devono scaricare)
  • Uso inappropriato delle rotazioni fisiche/server al posto di omega
  • Gestori di eventi superflui (contatto, collisione, ...)
  • Grande quantità di email o IM (messaggi immediati)
  • Algoritmi inefficienti (come la ricerca lineare)
  • Cicli di verifica dello stato di occupato (polling)

Progettazione efficiente

Ogni script inattivo in un oggetto aggiunge da 0.001 a 0.003 millisecondi per frame di uso del tempo di script. Pochi script è meglio.

  • Se avete necessità di un gruppo di "pulsanti", non inserite uno script in ogni primitiva. Usate invece llDetectedLinkNumber per ricavare quale pulsante è stato attivato dal vostro script principale.
  • Se avete necessità di modificare colore, alpha, o texture di primitive figlie, non inserite uno script in ogni primitiva. Usate invece llSetLinkAlpha, llSetLinkColor, llSetLinkTexture, o llSetLinkPrimitiveParams.
  • Non inserite mai uno script in ogni primitiva (di un grande insieme) che ascolta il canale 0 (o qualsiasi altro canale). Questa è probabilmente la cosa peggiore che si possa fare per l'efficienza. Sfortunatamente ciò è ampiamente diffuso.
  • Valutate l'uso di XyzzyText al posto di XyText.

La considerazione ultima è, se siete tentati di inserire uno script in ogni primitiva, fermatevi e pensate come potreste farlo in modo diverso con meno script. C'è quasi sempre un'alternativa. Sta a voi valutare se l'alternativa è utile alla vostra applicazione.

Micro-ottimizzazione

Ci sono molti modi per velocizzare gli script, come utilizzare ++a invece di a++, comunque, la maggior parte di queste micro ottimizzazioni potrebbero essere inutili in futuro.

Quanto è veloce questo codice

Il codice seguente calcolerà il tempo per ogni chiamata di funzione in millisecondi.

Siete pregati di proporre cambiamenti alla tab di discussione. Cortesemente non modificate il codice qui presente senza discussione, poichè ogni piccolo cambiamento potrebbe ridurre l'accuratezza delle misure. Prego notare che questo codice e i suoi commenti dovrebbero rispecchiare esattamente il codice e i commenti presentati nella pagina Efficiency Tester.

Ringraziamenti vanno a Xaviar Czervik per il codice originale, a Strife Onizuka per la messa a punto del codice per produrre misure più accurate e agli altri che hanno contribuito e sono elencati nella storia di questo articolo.

//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.");
  }
}

Efficienza

I dati seguenti sono stati raccolti usando la funzione precedente in una simulazione vuota (non privata) rilasciata di recente, con un solo script in esecuzione dentro un collegamento HUD. Sono stati eseguiti 20 test e ne è stata calcolata la media.

  ++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

Quindi a++ impiega il 40% di tempo in più che ++a (stima approssimativa).

Anche se i dati seguenti sono corretti, la funzione di cui sopra non è stata utilizzata. E' stata usata una versione leggermente meno ottimizzata, scritta da Xaviar Czervik. Se qualcuno potesse cortesemente ripetere i test con la funzione precedente.

  ++a:     0.364700 ms
  a += 1:  0.346900 ms
  a++:     0.413700 ms

Provando la stessa funzione in cicli for:

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

llOwnerSay , llSay , llShout , llWhisper (Canale 0 ove applicabile):

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

Canali differenti (llSay() per tutti):

  -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

Quantità di testo (llSay() e Canale 1 usato per tutti):

   1 Carattere:   1.242300 ms
   10 Caratteri:  1.309700 ms
   100 Caratteri: 1.965600 ms