|
|
Line 1: |
Line 1: |
| I've gone ahead and created this [[Code Racer]] page -- I think the approach is complete enough to be worth discussing - ''e.g.'', I get insight into [[llGetSubString]] snippets. However, something fiddly is still wrong with the implementation, I guess. As you can see in the sample results, often the sums of wins exceed the scale. -- [[User:Ppaatt Lynagh|Ppaatt Lynagh]] 18:08, 16 October 2007 (PDT)
| | This page intentionally left mostly blank. |
| | |
| Ha! Those new insights were half-grounded in nonsense! Half the win counts were wrong, courtesy one typo. Fixed now, maybe. -- [[User:Ppaatt Lynagh|Ppaatt Lynagh]] 21:18, 16 October 2007 (PDT)
| |
| | |
| [[Talk:Hex]] suggests that we should tweak this instrument to call [[llGetTime]] rather than [[llGetTimestamp]], in order to more accurately measure elapsed run time when time dilates. -- [[User:Ppaatt Lynagh|Ppaatt Lynagh]] 21:41, 19 October 2007 (PDT)
| |
| | |
| Change complete! Runs wonderfully faster too. The run time cost of the harness has dropped below two milliseconds. -- [[User:Ppaatt Lynagh|Ppaatt Lynagh]] 07:32, 20 October 2007 (PDT)
| |
| | |
| This should run indefinitely many versions of code against each other in parallel, so that we can complete an analysis like comparing all the too many versions of code at [[hex]] without attending the experiment. Also the last version of code could be an empty block of code, to measure the overhead of the harness, to throw it out, like the [[Efficiency Tester]] does. -- [[User:Ppaatt Lynagh|Ppaatt Lynagh]] 13:14, 22 October 2007 (PDT)
| |
| | |
| Below is a start towards running indefinitely many versions of code, without bias in favour of any one. -- [[User:Ppaatt Lynagh|Ppaatt Lynagh]] 16:02, 22 October 2007 (PDT)
| |
| | |
| <pre>
| |
| // Race a few version of code in dilated script time as measured by llGetTime.
| |
| // http://wiki.secondlife.com/wiki/Code_Racer
| |
| | |
| // List every runnable version.
| |
| | |
| list theRunners = [0, 1, 2];
| |
| | |
| // Count runnable versions.
| |
| | |
| integer theRunnable;
| |
| | |
| // Count votes to place.
| |
| | |
| list theVotes;
| |
| | |
| // Sum the run times observed.
| |
| | |
| list theSums;
| |
| | |
| // Count the races that ran without time running backwards.
| |
| | |
| integer theAverageable;
| |
| | |
| // Race no code alongside the other code in order to measure overhead.
| |
| | |
| runner0()
| |
| {
| |
| }
| |
| | |
| // Race a few versions of code.
| |
| | |
| runner1()
| |
| {
| |
| integer spinning;
| |
| for (spinning = 0; spinning < 25; ++spinning)
| |
| ;
| |
| }
| |
| | |
| runner2()
| |
| {
| |
| integer spinning;
| |
| for (spinning = 0; spinning < 50; ++spinning)
| |
| ;
| |
| }
| |
| | |
| runner3()
| |
| {
| |
| }
| |
| | |
| runner4()
| |
| {
| |
| }
| |
| | |
| runner5()
| |
| {
| |
| }
| |
| | |
| // Run the chosen runner once.
| |
| // Run thru an equal time while choosing any runner.
| |
| | |
| run(integer runner)
| |
| {
| |
| if (runner == 0) { runner0(); }
| |
| if (runner == 1) { runner1(); }
| |
| if (runner == 2) { runner2(); }
| |
| if (runner == 3) { runner3(); }
| |
| if (runner == 4) { runner4(); }
| |
| if (runner == 5) { runner5(); }
| |
| }
| |
| | |
| // Start up.
| |
| | |
| startup()
| |
| {
| |
| llOwnerSay("");
| |
| llOwnerSay("Click Running = No to stop this script after you've seen enough ...");
| |
| llOwnerSay(llGetTimestamp());
| |
| }
| |
| | |
| // Measure the race in calendar time elapsed since the minute began,
| |
| // if called in place of llGetTime.
| |
| //
| |
| // Note: "YYYY-MM-DDThh:mm:ss.ff..fZ" = llGetTimestamp();
| |
| // Note: 17 = 0 + llStringLength("YYYY-MM-DDThh:mm:")
| |
| // Note: -2 = -1 - llStringLength("Z")
| |
| | |
| float getTime()
| |
| {
| |
| return (float) llGetSubString(llGetTimestamp(), 17, -2); // "ss.ff..f"
| |
| }
| |
| | |
| // Race the runners and return the times when each ran.
| |
| // Run in llGetTime dilated time or in getTime calendar time.
| |
| | |
| list eachRunnerRun()
| |
| {
| |
| list befores = [];
| |
| integer runnablePlus = theRunnable + 1;
| |
| integer running;
| |
| for (running = 0; running < runnablePlus; ++running)
| |
| {
| |
| integer running = llList2Integer(theRunners, running);
| |
| befores += llGetTime();
| |
| run(running);
| |
| }
| |
| return befores;
| |
| }
| |
| | |
| // Return elapsed run time per runner,
| |
| // else return [] if time ran backwards.
| |
| | |
| list getRuntimesElseNone(list befores)
| |
| {
| |
| list runtimes = [];
| |
| float before = llList2Float(befores, 0);
| |
| integer timing;
| |
| for (timing = 0; timing < theRunnable; ++timing)
| |
| {
| |
| float after = llList2Float(befores, timing + 1);
| |
| float runtime = after - before;
| |
| if (runtime < 0.0) return [];
| |
| runtimes += runtime;
| |
| before = after;
| |
| }
| |
| return runtimes;
| |
| }
| |
| | |
| // Add to a listed float.
| |
| | |
| list addFloat(list sums, integer index, float addition)
| |
| {
| |
| list results = [];
| |
| integer summable = llGetListLength(sums);
| |
| integer summing;
| |
| for (summing = 0; summing < summable; ++summing)
| |
| {
| |
| float result = llList2Float(sums, summing);
| |
| if (index == summing)
| |
| {
| |
| result += addition;
| |
| }
| |
| results += result;
| |
| }
| |
| return results;
| |
| }
| |
| | |
| // Add to a listed integer.
| |
| | |
| list addInteger(list sums, integer index, integer addition)
| |
| {
| |
| list results = [];
| |
| integer summable = llGetListLength(sums);
| |
| integer summing;
| |
| for (summing = 0; summing < summable; ++summing)
| |
| {
| |
| integer result = llList2Integer(sums, summing);
| |
| if (index == summing)
| |
| {
| |
| result += addition;
| |
| }
| |
| results += result;
| |
| }
| |
| return results;
| |
| }
| |
| | |
| // Race the runners once, vote to place, and sum run time per runner.
| |
| | |
| runRace()
| |
| {
| |
| | |
| // Race the runners once.
| |
| | |
| list runtimes = getRuntimesElseNone(eachRunnerRun());
| |
| // llOwnerSay("[" + llDumpList2String(runtimes, ", ") + "] == runtimes");
| |
| | |
| // Sort the runtimes into places.
| |
| | |
| list places = llListSort(runtimes, 1, TRUE); // sort least to most
| |
| integer placeable = llGetListLength(places); // 0 or theRunnable
| |
| | |
| // Sum run time per runner.
| |
| | |
| integer adding;
| |
| for (adding = 0; adding < placeable; ++adding)
| |
| {
| |
| integer running = llList2Integer(theRunners, adding);
| |
| float runtime = llList2Float(runtimes, adding);
| |
| theSums = addFloat(theSums, running, runtime);
| |
| ++theAverageable;
| |
| | |
| // Vote to place at each equal runtime.
| |
| | |
| integer placing;
| |
| for (placing = 0; placing < placeable; ++placing)
| |
| {
| |
| float placed = llList2Float(places, placing);
| |
| if (runtime == placed)
| |
| {
| |
| integer flat = (running * placeable) + placing;
| |
| theVotes = addInteger(theVotes, flat, 1);
| |
| }
| |
| }
| |
| }
| |
| }
| |
| | |
| // Start up a burst of races.
| |
| | |
| zeroBurst()
| |
| {
| |
| theSums = theVotes = [];
| |
| theRunnable = llGetListLength(theRunners);
| |
| integer placing;
| |
| for (placing = 0; placing < theRunnable; ++placing)
| |
| {
| |
| theSums += 0.0;
| |
| integer running;
| |
| for (running = 0; running < theRunnable; ++running)
| |
| {
| |
| theVotes += 0;
| |
| }
| |
| }
| |
| }
| |
| | |
| // Report a burst of races.
| |
| | |
| reportBurst(integer scaling)
| |
| {
| |
| | |
| // Consider each place.
| |
| | |
| integer placing;
| |
| for (placing = 0; placing < theRunnable; ++placing)
| |
| {
| |
| list votes = llList2ListStrided(llList2List(theVotes, placing, -1), 0, -1, theRunnable);
| |
| integer winner = llList2Integer(llListSort(votes, 1, TRUE), -1);
| |
| | |
| // Find the winner (or the winners) of that place.
| |
| | |
| integer running;
| |
| for (running = 1; running < theRunnable; ++running)
| |
| {
| |
| integer vote4place = llList2Integer(votes, running);
| |
| if (vote4place == winner)
| |
| {
| |
| | |
| // Describe a winner.
| |
| | |
| float summed = llList2Float(theSums, running) - llList2Float(theSums, 0);
| |
| float average = 1000.0 * (summed / theAverageable);
| |
| | |
| llOwnerSay("~" +
| |
| (string) average + " ms elapsed in version " + (string) running +
| |
| " to place at " + (string) placing +
| |
| " by " + (string) vote4place + " of " + (string) scaling + " votes"
| |
| );
| |
| }
| |
| }
| |
| }
| |
| }
| |
| | |
| // Run a few bursts of races at each scale, for indefinitely increasing scale.
| |
| | |
| runRaceRepeatedly()
| |
| {
| |
| integer scaleable = 10;
| |
| integer repeatable = 1; // don't bother to repeat the first burst
| |
| while (TRUE)
| |
| {
| |
| integer repeating;
| |
| for (repeating = 0; repeating < repeatable; ++repeating)
| |
| {
| |
| zeroBurst();
| |
| | |
| integer scaling;
| |
| for (scaling = 0; scaling < scaleable; ++scaling)
| |
| {
| |
| runRace();
| |
| theRunners = llList2List(theRunners, -1, -1) + llList2List(theRunners, 0, -2);
| |
| }
| |
| | |
| llOwnerSay("");
| |
| reportBurst(scaling);
| |
| llOwnerSay(llGetTimestamp());
| |
| }
| |
|
| |
| scaleable *= 10;
| |
| repeatable = 3; // repeat most bursts several times
| |
| }
| |
| }
| |
| | |
| // Race to measure relative run-time cost of multiple versions of code.
| |
| // Produce unreasonable answers when the run-time cost measured equals or exceeds 60 seconds.
| |
| | |
| default
| |
| {
| |
| state_entry()
| |
| {
| |
| startup();
| |
| runRaceRepeatedly();
| |
| }
| |
| }
| |
| </pre>
| |