User:Becky Pippen/Measure Script Memory Usage

From Second Life Wiki
< User:Becky Pippen
Revision as of 16:01, 12 December 2009 by Becky Pippen (talk | contribs) (preliminary page related to upcoming script memory limits)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Measuring Script Memory Usage

In addition to upcoming new tools that will let us conveniently measure scripts in use, scripters can also use llGetFreeMemory() to make more detailed measurements of how specific functions or statements affect memory usage.

The memory a script uses is:

  • Starting memory (65536 bytes for Mono, 16384 for LSL)
  • minus program statements (e.g., a = 2;)
  • minus static (pre-defined) variables (e.g., integer a;)
  • minus dynamic (created when running) data and overhead (e.g., f("a" + "b") )

Here is an LSL statement that reports how much free memory you have at the moment it's called:

llOwnerSay((string)llGetFreeMemory() + " bytes free");

To report how much memory is used (instead of free) in a Mono script, subtract free from total memory:

llOwnerSay((string)(65536 - llGetFreeMemory()) + " bytes used");

For LSL-compiled scripts, change 65536 to 16384.

It makes a difference where you place llGetFreeMemory() in your script. To see how much memory is used by the script's program code and static (pre-defined) variables, put llGetFreeMemory() as the first line in state_entry() or on_rez() in the default state. To see how much memory your script used including all runtime dynamic data, run llGetFreeMemory() as the last statement executed after your script has created all the data it's going to.

To see how much memory is used by a one or a few program statements, measure the memory before and after and take the difference. Be aware that your instrumentation for measuring memory might itself consume some memory if it uses variables or function calls, so do all that prior to the measurement. Also be aware that the way the LSL and Mono back ends allocate memory (and perhaps from fluctuations due to garbage collection), you might get varying results from individual measurements, so it's sometimes useful to take an average.

For example, suppose we want to measure how much memory gets consumed each time your script saves a short string to a global list. Here is the statement that we want to measure:

aList += "hello";  // appends one 5-char string to the list

To measure the memory used by this statement, we'll average the memory consumption over a hundred loops. We'll also globally declare the temporary variables we'll need for the measurement so that between the start and end of the test, there will be no extra variables allocated or function calls made except the code being measured:

list aList;
integer startFreeMem;
integer endFreeMem;

default
{
    touch_start(integer num)
    {
       integer loops = 100;
       startFreeMem = llGetFreeMemory();

       while (--loops >= 0) {
           aList += "hello";  // appends one 5-char string to the list
       }

       endFreeMem = llGetFreeMemory();
       llOwnerSay("Change in free mem: " + (string)(startFreeMem - endFreeMem));
    }
}

By the way, the results I got from this test shows that it takes 3486 bytes of memory to append 100 copies of "hello" to a global list when compiled with LSL, and 752 bytes when compiled with Mono. These results are a little different than those given in [this page], and that's why it can be illuminating to make these measurements in your own scripts.