LSL Script Efficiency/it
LSL Portal | Functions | Events | Types | Operators | Constants | Flow Control | Script Library | Categorized Library | Tutorials |
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 modficate 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