Difference between revisions of "Efficiency Tester"

From Second Life Wiki
Jump to navigation Jump to search
m (For a less brief discussion, see: LSL Script Efficiency)
m (Replaced <source> with <syntaxhighlight>)
 
(19 intermediate revisions by 3 users not shown)
Line 1: Line 1:
{{LSL Header}}
{{LSL Header}}


Want to see how small some code is? Add three copies of your code to a script, call [[llGetFreeMemory]] to count free space, and start deleting copies. After deleting each copy, you should see a consistent savings in free space, ''i.e'', the code space cost of your code.
'''Q1: Want to see how small some code compiles?'''


Want to see how fast some code is? Run your code inside code like this example to call your code time and again to measure the consequent change in [[llGetTimestamp]].
'''A:''' See the [[Code Sizer]] harness for [[llGetFreeMemory]].


Please understand, we don't mean to be arguing for many different ways to measure the costs of code. We do mean to be building a consensus on best practices, in one considerately short article constructed from a neutral point of view.
'''Q2: Want to discover quickly if a change to code makes the code run faster?'''


'''A:''' See the [[Code Racer]] harness for [[llGetTimestamp]].
'''Q3: Want to see approximately how fast some code runs?'''
'''A:''' Run your code inside code like this example to call your code time and again to measure the consequent change in [[llGetTimestamp]].
Sample Results:
<pre>
<pre>
//IMPORTANT: Only perform tests in an empty region.
15249 free bytes of code at default.state_entry
0.177314+-??% ms may have elapsed on average in each of
10000 trials of running the code in the loop
0.176341+-??% ms may have elapsed on average in each of
10000 trials of running the code in the loop
0.201925+-??% ms may have elapsed on average in each of
10000 trials of running the code in the loop
</pre>
 
Code:
 
<syntaxhighlight lang="lsl2">
// IMPORTANT:
// Only perform tests in an empty region.
// To reduce contamination and be sure to wearing no attachments.
// To reduce contamination and be sure to wearing no attachments.
// Preferably do tests in a private sim with one on it.
// Preferably do tests in a private sim with one on it.
Line 14: Line 34:
// There is a margin of error so run the tests multiple times to determine it.
// There is a margin of error so run the tests multiple times to determine it.


integer time() { // count milliseconds since the day began
// (16384 - (15267 - 18)) was the well-known byte code size of this llGetTime/ llGetTimestamp harness
 
// Measure the race instead
// in calendar milliseconds elapsed since the day began,
// if called in place of llGetTime.
 
integer getTime() // count milliseconds since the day began
{
     string stamp = llGetTimestamp(); // "YYYY-MM-DDThh:mm:ss.ff..fZ"
     string stamp = llGetTimestamp(); // "YYYY-MM-DDThh:mm:ss.ff..fZ"
     return (integer) llGetSubString(stamp, 11, 12) * 3600000 + // hh
     return (integer) llGetSubString(stamp, 11, 12) * 3600000 + // hh
Line 21: Line 48:
}
}


default {
default
  state_entry() {
{
    state_entry()
    {
 
        // always measure how small, not only how fast
 
        llOwnerSay((string) llGetFreeMemory() + " free bytes of code at default.state_entry");
 
        // always take more than one measurement
 
        integer repeateds;
        for (repeateds = 0; repeateds < 3; ++repeateds)
        {
 
            // declare test variables
 
            float counter;
 
            // declare framework variables
 
            float i = 0;
            float j = 0;
            integer max = 10000; // 2ms of work takes 20 seconds to repeat 10,000 times, plus overhead


    //test variables
            // begin
    float counter;


    //framework variables
            float t0 = llGetTime();
    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();
            // loop to measure elapsed time to run sample code
    do {


      //test
            do
      counter += 1;
            {
 
              // test once or more
 
              counter += 1; // 18 bytes is the well-known byte code size of this sourceline
        
        
    }while (++i < max);
            } while (++i < max);
    float t1 = time();
 
    do ; while (++j < max);
            float t1 = llGetTime();
    float t2 = time();//remove the time required by the framework
 
    float elapsed = ((t1 - t0) - (t2 - t1))/max;
            // loop to measure elapsed time to run no code
    llOwnerSay("The function in the loop took a total of " + (string)elapsed + " milliseconds.");
 
  }
            do ; while (++j < max);
 
            float t2 = llGetTime();
 
            // complain if time ran backwards
           
            if (!((t0 <= t1) && (t1 <= t2)))
            {
                llOwnerSay("MEANINGLESS RESULT -- SIMULATED TIME RAN BACKWARDS -- TRY AGAIN");
            }
           
            // report average time elapsed per run
 
            float elapsedms = 1000.0 * (((t1 - t0) - (t2 - t1)) / max);
            llOwnerSay((string) elapsedms + "+-??% ms may have elapsed on average in each of");
            llOwnerSay((string) max + " trials of running the code in the loop");
        }
    }
}
}
</pre>
</syntaxhighlight>
 
Launched by [[User:Xaviar Czervik|Xaviar Czervik]], then modified by [[User:Strife Onizuka|Strife Onizuka]], then further edited as the history of this article shows.


Copy-edited by [[User:Xaviar Czervik|Xaviar Czervik]], then modified by [[User:Strife Onizuka|Strife Onizuka]], then further edited as the history of this article shows.
Try the empty test of deleting the { counter += 1; } source line to see the astonishing inaccuracy of this instrument. The time cost of no code, as measured here, isn't always zero!


For a less brief discussion, see: [[LSL Script Efficiency]]
See the [[LSL Script Efficiency]] article for a less brief discussion. Please understand, we don't mean to be arguing for many different ways to measure the costs of code. Here we do mean to be building a consensus on best practices, in one considerately short article constructed from a neutral point of view.


{{LSLC|Library}}{{LSLC|Examples}}
{{LSLC|Library}}{{LSLC|Examples}}

Latest revision as of 01:50, 9 September 2023

Q1: Want to see how small some code compiles?

A: See the Code Sizer harness for llGetFreeMemory.

Q2: Want to discover quickly if a change to code makes the code run faster?

A: See the Code Racer harness for llGetTimestamp.

Q3: Want to see approximately how fast some code runs?

A: Run your code inside code like this example to call your code time and again to measure the consequent change in llGetTimestamp.

Sample Results:

15249 free bytes of code at default.state_entry
0.177314+-??% ms may have elapsed on average in each of
10000 trials of running the code in the loop
0.176341+-??% ms may have elapsed on average in each of
10000 trials of running the code in the loop
0.201925+-??% ms may have elapsed on average in each of
10000 trials of running the code in the loop

Code:

// 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.

// (16384 - (15267 - 18)) was the well-known byte code size of this llGetTime/ llGetTimestamp harness

// Measure the race instead
// in calendar milliseconds elapsed since the day began,
// if called in place of llGetTime.

integer getTime() // 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()
    {

        // always measure how small, not only how fast

        llOwnerSay((string) llGetFreeMemory() + " free bytes of code at default.state_entry");

        // always take more than one measurement

        integer repeateds;
        for (repeateds = 0; repeateds < 3; ++repeateds)
        {

            // declare test variables

            float counter;

            // declare framework variables

            float i = 0;
            float j = 0;
            integer max = 10000; // 2ms of work takes 20 seconds to repeat 10,000 times, plus overhead

            // begin

            float t0 = llGetTime();

            // loop to measure elapsed time to run sample code

            do
            {

              // test once or more

              counter += 1; // 18 bytes is the well-known byte code size of this sourceline
      
            } while (++i < max);

            float t1 = llGetTime();

            // loop to measure elapsed time to run no code

            do ; while (++j < max);

            float t2 = llGetTime();

            // complain if time ran backwards
            
            if (!((t0 <= t1) && (t1 <= t2)))
            {
                llOwnerSay("MEANINGLESS RESULT -- SIMULATED TIME RAN BACKWARDS -- TRY AGAIN");
            }
            
            // report average time elapsed per run

            float elapsedms = 1000.0 * (((t1 - t0) - (t2 - t1)) / max);
            llOwnerSay((string) elapsedms + "+-??% ms may have elapsed on average in each of");
            llOwnerSay((string) max + " trials of running the code in the loop");
        }
    }
}

Launched by Xaviar Czervik, then modified by Strife Onizuka, then further edited as the history of this article shows.

Try the empty test of deleting the { counter += 1; } source line to see the astonishing inaccuracy of this instrument. The time cost of no code, as measured here, isn't always zero!

See the LSL Script Efficiency article for a less brief discussion. Please understand, we don't mean to be arguing for many different ways to measure the costs of code. Here we do mean to be building a consensus on best practices, in one considerately short article constructed from a neutral point of view.