Difference between revisions of "Talk:Efficiency Tester"
Jump to navigation
Jump to search
(Change complete! The run time cost of the harness may have dropped to below 0.5 milliseconds. -- ~~~~) |
(share the hex example of an elusive run time you could try to measure convincingly) |
||
Line 1: | Line 1: | ||
[[ | = The Elusive Run-Time of [[Hex]] = | ||
I'm next trying runs of the following instance of an llGetTime [[Efficiency Tester]]. You see five source lines commented out near the string "test once or more" ... I'm measuring the near zero cost of running with all five commented out, the max cost of none of the five commented out, and the individual costs of commenting in one line at a time ... We'll see if those results make sense, when they eventually appear. -- [[User:Ppaatt Lynagh|Ppaatt Lynagh]] 10:57, 27 October 2007 (PDT) | |||
<pre> | |||
// Race a few versions of code. | |||
// http://wiki.secondlife.com/wiki/hex | |||
string XDIGITS1 = "0123456789abcdef"; // could be "0123456789ABCDEF" | |||
string hexes1(integer bits) | |||
{ | |||
string nybbles = ""; | |||
while (bits) | |||
{ | |||
integer lsn = bits & 0xF; // least significant nybble | |||
string nybble = llGetSubString(XDIGITS1, lsn, lsn); | |||
nybbles = nybble + nybbles; | |||
bits = bits >> 4; // discard the least significant bits at right | |||
bits = bits & 0xfffFFFF; // discard the sign bits at left | |||
} | |||
return nybbles; | |||
} | |||
string hex1(integer value) | |||
{ | |||
if (value < 0) | |||
{ | |||
return "-0x" + hexes1(-value); | |||
} | |||
else if (value == 0) | |||
{ | |||
return "0x0"; // hexes(value) == "" when (value == 0) | |||
} | |||
else // if (0 < value) | |||
{ | |||
return "0x" + hexes1(value); | |||
} | |||
} | |||
// http://wiki.secondlife.com/wiki/hex | |||
string hex2(integer value) | |||
{ | |||
string lead = "0x"; | |||
if (value & 0x80000000) // means (integer < 0) but is smaller and faster | |||
{ | |||
lead = "-0x"; | |||
value = -value; // unnecessary when value == -0x80000000 | |||
} | |||
string nybbles = ""; | |||
do | |||
{ | |||
integer lsn = value & 0xF; // least significant nybble | |||
nybbles = llGetSubString("0123456789abcdef", lsn, lsn) + nybbles; | |||
} while ((value = (0xfffFFFF & (value >> 4)))); | |||
return lead + nybbles; | |||
} | |||
string hex3(integer value) | |||
{ | |||
string lead = "0x"; | |||
if (value & 0x80000000) // means (integer < 0) but is smaller and faster | |||
{ | |||
lead = "-0x"; | |||
value = -value; // unnecessary when value == -0x80000000 | |||
} | |||
integer lsn; // least significant nybble | |||
string nybbles = ""; | |||
do | |||
{ | |||
nybbles = llGetSubString("0123456789abcdef", lsn = (value & 0xF), lsn) + nybbles; | |||
} | |||
while ((value = (0xfffFFFF & (value >> 4)))); | |||
return lead + nybbles; | |||
} | |||
// http://wiki.secondlife.com/wiki/hex | |||
string bits2nybbles4(integer bits) | |||
{ | |||
string nybbles = ""; | |||
do | |||
{ | |||
integer lsn = bits & 0xF; // least significant nybble | |||
nybbles = llGetSubString("0123456789ABCDEF", lsn, lsn) + nybbles; | |||
} while (bits = (0xfffFFFF & (bits >> 4))); | |||
return nybbles; | |||
} | |||
// http://wiki.secondlife.com/wiki/Talk:hex | |||
string bits2nybbles5(integer bits) | |||
{ | |||
integer lsn; // least significant nybble | |||
string nybbles = ""; | |||
do | |||
{ | |||
integer lsn = bits & 0xF; // least significant nybble | |||
nybbles = llGetSubString("0123456789ABCDEF", lsn = (bits & 0xF), lsn) + nybbles; | |||
} while (bits = (0xfffFFFF & (bits >> 4))); | |||
return nybbles; | |||
} | |||
// 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 | |||
// hex1(0x7fffFFFF); | |||
// hex2(0x7fffFFFF); | |||
// hex3(0x7fffFFFF); | |||
// bits2nybbles4(0x7fffFFFF); | |||
// bits2nybbles5(0x7fffFFFF); | |||
} 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"); | |||
} | |||
} | |||
} | |||
</pre> |
Revision as of 09:57, 27 October 2007
The Elusive Run-Time of Hex
I'm next trying runs of the following instance of an llGetTime Efficiency Tester. You see five source lines commented out near the string "test once or more" ... I'm measuring the near zero cost of running with all five commented out, the max cost of none of the five commented out, and the individual costs of commenting in one line at a time ... We'll see if those results make sense, when they eventually appear. -- Ppaatt Lynagh 10:57, 27 October 2007 (PDT)
// Race a few versions of code. // http://wiki.secondlife.com/wiki/hex string XDIGITS1 = "0123456789abcdef"; // could be "0123456789ABCDEF" string hexes1(integer bits) { string nybbles = ""; while (bits) { integer lsn = bits & 0xF; // least significant nybble string nybble = llGetSubString(XDIGITS1, lsn, lsn); nybbles = nybble + nybbles; bits = bits >> 4; // discard the least significant bits at right bits = bits & 0xfffFFFF; // discard the sign bits at left } return nybbles; } string hex1(integer value) { if (value < 0) { return "-0x" + hexes1(-value); } else if (value == 0) { return "0x0"; // hexes(value) == "" when (value == 0) } else // if (0 < value) { return "0x" + hexes1(value); } } // http://wiki.secondlife.com/wiki/hex string hex2(integer value) { string lead = "0x"; if (value & 0x80000000) // means (integer < 0) but is smaller and faster { lead = "-0x"; value = -value; // unnecessary when value == -0x80000000 } string nybbles = ""; do { integer lsn = value & 0xF; // least significant nybble nybbles = llGetSubString("0123456789abcdef", lsn, lsn) + nybbles; } while ((value = (0xfffFFFF & (value >> 4)))); return lead + nybbles; } string hex3(integer value) { string lead = "0x"; if (value & 0x80000000) // means (integer < 0) but is smaller and faster { lead = "-0x"; value = -value; // unnecessary when value == -0x80000000 } integer lsn; // least significant nybble string nybbles = ""; do { nybbles = llGetSubString("0123456789abcdef", lsn = (value & 0xF), lsn) + nybbles; } while ((value = (0xfffFFFF & (value >> 4)))); return lead + nybbles; } // http://wiki.secondlife.com/wiki/hex string bits2nybbles4(integer bits) { string nybbles = ""; do { integer lsn = bits & 0xF; // least significant nybble nybbles = llGetSubString("0123456789ABCDEF", lsn, lsn) + nybbles; } while (bits = (0xfffFFFF & (bits >> 4))); return nybbles; } // http://wiki.secondlife.com/wiki/Talk:hex string bits2nybbles5(integer bits) { integer lsn; // least significant nybble string nybbles = ""; do { integer lsn = bits & 0xF; // least significant nybble nybbles = llGetSubString("0123456789ABCDEF", lsn = (bits & 0xF), lsn) + nybbles; } while (bits = (0xfffFFFF & (bits >> 4))); return nybbles; } // 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 // hex1(0x7fffFFFF); // hex2(0x7fffFFFF); // hex3(0x7fffFFFF); // bits2nybbles4(0x7fffFFFF); // bits2nybbles5(0x7fffFFFF); } 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"); } } }