Difference between revisions of "Efficiency Tester"

From Second Life Wiki
Jump to navigation Jump to search
m (Replaced <source> with <syntaxhighlight>)
 
(23 intermediate revisions by 3 users not shown)
Line 1: Line 1:
{{LSL Header}}
{{LSL Header}}


Written by [[User:Xaviar Czervik|Xaviar Czervik]], Modified by [[User:Strife Onizuka|Strife Onizuka]].
'''Q1: Want to see how small some code compiles?'''


This code will test the efficiency of what ever is in the while loop.  
'''A:''' See the [[Code Sizer]] harness for [[llGetFreeMemory]].


I've used i += 1 because I found it to be faster on the [[LSL Script Efficiency]] page.
'''Q2: Want to discover quickly if a change to code makes the code run faster?'''


Lots of people disagree with me that a += 1 is faster than ++a... If you don't like it, change it and then sue me :P.  
'''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 to reduce contamination and be sure to wearing no attachments.
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.
// 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 time() {
integer getTime() // count milliseconds since the day began
     string stamp = llGetTimestamp();
{
     return (integer) llGetSubString(stamp, 11, 12) * 3600000 +  
     string stamp = llGetTimestamp(); // "YYYY-MM-DDThh:mm:ss.ff..fZ"
           (integer) llGetSubString(stamp, 14, 15) * 60000 +  
     return (integer) llGetSubString(stamp, 11, 12) * 3600000 + // hh
           llRound((float)llGetSubString(stamp, 17, -2) * 1000000.0)/1000;
           (integer) llGetSubString(stamp, 14, 15) * 60000 + // mm
//llInsertString(llDeleteSubString(stamp, 19, 19) + "000000", 23, ".")
           llRound((float)llGetSubString(stamp, 17, -2) * 1000000.0)/1000; // ss.ff..f
}
}


default {
default
  state_entry() {
{
     //test variables
    state_entry()
    float counter;
     {


    //framework variables
        // always measure how small, not only how fast
    float i = 0;
 
    float j = 0;
        llOwnerSay((string) llGetFreeMemory() + " free bytes of code at default.state_entry");
    float max = 10000;
 
    float start = time();
        // always take more than one measurement
    do {
 
      //test
        integer repeateds;
      counter += 1;
        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);
            } while (++i < max);
    float delta = time();
 
    do ; while (++j < max);
            float t1 = llGetTime();
    float end = time();//remove the time required by the framework
 
    float t = ((delta - start) - (end - delta))/max;
            // loop to measure elapsed time to run no code
    llOwnerSay("The function in the loop took a total of " + (string)t + " 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.
 
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.


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