LibraryPrecisionTime
De DigiWiki.
This is a chunk of code to show you two things.
1) llSetTimerEvent's precision is ridiculously low.
2) You can easily improve the precision by setting the timer a bit short and then waiting until your target time.
How do you use this script?
1) If you cut and paste this code into a script and put it into a box, it will send periodic messages displaying how far off llSetTimerEvent is from where it should be, in seconds.
2) If you change the first line to "integer useprectimer = 1;" it will send periodic messages displaying how close a precision timer can get.
3) If you read the timer event at the bottom, and precTimer() function at the top, they demonstrate the precision timer.
//-------------------------- // precision timer //-------------------------- integer useprectimer = 0; // 0 for settimerevent, 1 for precision timer float timetotest = 0.2; // how fast should the timer run? // these two functions set timers with and without precision, and mark the desired time target vector timeTarget; precTimer( float secdiff ) { timeTarget = vecTime(); timeTarget.z += secdiff; llSetTimerEvent(secdiff - 0.05); } nonprecTimer( float secdiff ) { timeTarget = vecTime(); timeTarget.z += secdiff; llSetTimerEvent(secdiff); } // run a report of how well the timer is doing runReport() { float min; float max; float avg; float total; float cur; integer i; integer len; llSetTimerEvent(0.0); // try to clear the event queue up a bit, altho reset should do it if( useprectimer == 1 ) { llOwnerSay("Precision timer stats:"); } else { llOwnerSay("llSetTimerEvent stats:"); } len = llGetListLength(lDiffs); total = 0.0; min = 1.0; max = 0.0; for( i = 0; i < len; i++ ) { cur = llList2Float(lDiffs, i); total += cur; if( cur < min ) { min = cur; } if( cur > max ) { max = cur; } } avg = total/(float)len; llOwnerSay("Total drift: " + (string)total + ", timers run: " + (string)len); llOwnerSay("Avg drift: " + (string)avg); llOwnerSay("Min drift: " + (string)min); llOwnerSay("Max drift: " + (string)max); llOwnerSay("Starting another run."); llResetScript(); } //-------------------------- // time utility functions //-------------------------- vector vecTime() { vector tsp; list tsv; tsv = llParseString2List( llGetTimestamp(), ["T", ":", "Z"], [] ); tsp.x = llList2Integer(tsv, 1) - 8; if( tsp.x < 0 ) { tsp.x += 24; } tsp.y = llList2Integer(tsv, 2); tsp.z = llList2Float(tsv, 3); return tsp; } vector fixTime( vector inTime ) { vector oTime = inTime; while( oTime.z >= 60.0 ) { oTime.z -= 60.0; oTime.y++; } while( oTime.y >= 60.0 ) { oTime.y -= 60.0; oTime.z++; } return oTime; } float timeDiffNow( vector vTarget ) { vector vTime = vecTime(); return (vTarget.x - vTime.x)*3600.0 + (vTarget.y - vTime.y) * 60.0 + (vTarget.z - vTime.z); } // included for reference: float timeDiff( vector vMore, vector vLess ) { float hours = vMore.x - vLess.x; float minutes = vMore.y - vLess.y; float seconds = vMore.z - vLess.z; float tics = hours * 3600.0 + minutes * 60.0 + seconds; // llOwnerSay("Diff between " + (string)vMore + " and " + (string)vLess ); // llOwnerSay("Diff returned approx. " + (string)( (integer)tics ) + " seconds."); return tics; } //-------------------------- // PrecTimer script: report the drift in llSetTimerEvent, and show an easy way to fix it: //-------------------------- list lDiffs; // used to store statistics default { state_entry() { lDiffs = []; if( useprectimer == 1 ) { precTimer(timetotest); } else { nonprecTimer(timetotest); } } timer() { float timeleft = timeDiffNow(timeTarget); // ETA to target time if( useprectimer == 1 ) { //Begin very simple precision countdown: llResetTime(); while( (timeleft -= llGetAndResetTime()) > 0.01 ); //Reset the target of the precision timer: precTimer(timetotest); } else { //Reset the target of the nonprecision timer: timeTarget.z += timetotest; } lDiffs = (lDiffs=[]) + lDiffs + [llFabs(timeleft)]; if( llGetListLength(lDiffs) > 100 ) { runReport(); } } touch_start(integer nd) { runReport(); } }
Example output:
[15:57] Object: Precision timer stats: [15:57] Object: Total drift: 0.110259, timers run: 101 [15:57] Object: Avg drift: 0.001092 [15:57] Object: Min drift: 0.000000 [15:57] Object: Max drift: 0.080150 [15:59] Object: llSetTimerEvent stats: [15:59] Object: Total drift: 2.131889, timers run: 101 [15:59] Object: Avg drift: 0.021108 [15:59] Object: Min drift: 0.000084 [15:59] Object: Max drift: 0.101887
That's right... which do you want, a drift of 1/50th of a second, or of 1/1000th of a second? Yes. Use a precision timer.


