Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Tricks for saving string memory

Hewee Zetkin
Registered User
Join date: 20 Jul 2006
Posts: 2,702
01-06-2008 21:44
From: Lear Cale
Are you sure about this? That was my assumption too on first learning of the trick, so I did some testing and found that the memory was permanently lost (or rather, lost as long as the item remained in the list). It wasn't a rigorous test, and things may have changed since then. I'm interested in any information you have about this, thanks!


Most likely that is a symptom of the memory testing API. You can only get information about the LEAST amount of memory free since the script started running. You never see memory getting freed up. But we could test to be sure, since it has been a while since I did memory tests:

1. Allocate a list of N X-sized values (reasonably large).
2. Allocate a list of M X-sized values (reasonably large, and significanly different from N).
3. Execute: myNSizeList += myMSizeList;
4. Execute: myNSizeList += myMSizeList;
(Report free memory after each step.)

Now, if the differences in free memory are significantly different as caused by steps 3 and 4, then we're good. It means some of the memory that APPEARS to have been used by step 3 has then been deallocated before step 4 allocated more memory.
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
01-06-2008 22:08
the use of
mylist = (myList = []) + myList + element;
vs
myList += element;
or
myList = myList + element;

does not actually save Storage (heap) memory (as Hewee pointed out)
what it does is prevents the extraneous loading of the storage variable(into stack memnory), which effectively means there are two copies loaded when the second statment runs

with the first statment you clear the storage variable, THEN load it, so what you have in memory is what the variable will be, and an empty list

with the second statement you get what the list will be, and what it already is... which is about twice the memory of the first version.

it works because the operations are done last to first, so you end up building what will go into the container, clearing out what IS in the container, then adding what you built... vs loading what you built AND what you had, then replacing what you had with what you built
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Lear Cale
wordy bugger
Join date: 22 Aug 2007
Posts: 3,569
01-07-2008 04:58
From: Hewee Zetkin
Most likely that is a symptom of the memory testing API. You can only get information about the LEAST amount of memory free since the script started running. You never see memory getting freed up. But we could test to be sure, since it has been a while since I did memory tests:

1. Allocate a list of N X-sized values (reasonably large).
2. Allocate a list of M X-sized values (reasonably large, and significanly different from N).
3. Execute: myNSizeList += myMSizeList;
4. Execute: myNSizeList += myMSizeList;
(Report free memory after each step.)

Now, if the differences in free memory are significantly different as caused by steps 3 and 4, then we're good. It means some of the memory that APPEARS to have been used by step 3 has then been deallocated before step 4 allocated more memory.


My test was simpler and tested the hypothesis that the memory gains from the more complicated way to add a single item to a list are not merely temporary. I used a loop that added one item to the list N times. The memory savings for the more complicated method was proportional to both N and the size of the item being added. I believe that this proves that the savings is not merely temporary during the addition itself. However, it does not prove that the apparently "missing" memory is not available for further allocations of smaller items, which is likely to be the case.

I.e., the more efficient method simply reduced fragmentation; it doesn't cause less memory to be occupied per se. That's a different hypothesis than the one you mentioned in the first place, although it might have been what you had in mind.

That's what Void's post says, and it makes sense to me. However, why the interpreter loads a copy of the actual value of an lvalue is a mystery to me! (OK, ok, it's a simplification; it doesn't distinguish between values and lvalues, grrrr.)
Sindy Tsure
Will script for shoes
Join date: 18 Sep 2006
Posts: 4,103
01-07-2008 08:27
From: Void Singer
lol I just wrote almost exatly what meade wrote on your other thread... the basic principle is to eliminate repeated calls on indivdual if statmenets....

loading a debug message out to another script would likely be more effiecient in your example if you just sent a linked message with your debug info to the other script and let THAT script determine whether or not to say it.... in fact you'd only have to remove the debug script to remove the messages so wouldn't even need to determine an if condition (but you'd be left with all the extra link messages, so not optimal for the final usage

as a base rule if you find you are writing any block of code multpile times you should consider making it a function... and any function can be offloaded to a subscript (although with a certain amount of overhead, for messages and flow logic)... offloading can be tricky if you don't get the flow right, functions are not tricky at all because it's the same as inserting the code wherever it's called (with the slight overhead of passing variables in some cases)

I'm not sure I totally agree with this...

What Meade wrote on the previous page helps cut down the complexity of the script and saves a bit of static memory but LSL uses (I think - please correct me if I'm wrong) pass-by-value when calling functions. So, although the script is cleaner, it's more expensive at run time. This is why she said to be careful of calling it in a tight-loop...

Either way, whether it's scattered throughout the code or contained in one function, the 'if' is still going to get executed every time. If you're passing a string to a debug function, LSL is going to make a copy of that string (eating memory at least temporarily) each time it's called. If you're not passing strings, you're still adding the cost of pushing ints and a new stack frame. All of these are more expensive than doing it in-line..

If you're actually passing the string to a different script, that's even more expensive than doing it all within one script.

That said, I use debug functions like this, too - ain't saying they're bad, just that people should understand the implications.
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
01-07-2008 14:32
From: Sindy Tsure
I'm not sure I totally agree with this...

What Meade wrote on the previous page helps cut down the complexity of the script and saves a bit of static memory but LSL uses (I think - please correct me if I'm wrong) pass-by-value when calling functions. So, although the script is cleaner, it's more expensive at run time. This is why she said to be careful of calling it in a tight-loop...

Either way, whether it's scattered throughout the code or contained in one function, the 'if' is still going to get executed every time. If you're passing a string to a debug function, LSL is going to make a copy of that string (eating memory at least temporarily) each time it's called. If you're not passing strings, you're still adding the cost of pushing ints and a new stack frame. All of these are more expensive than doing it in-line..

If you're actually passing the string to a different script, that's even more expensive than doing it all within one script.

That said, I use debug functions like this, too - ain't saying they're bad, just that people should understand the implications.

for the second paragraph I was using Alicia's code to point out that she was still doing all the proccesing in her base script (sending the debug to a function, deciding wher or not to parse it THEN offloading it to another script... when it'd have been more effective just to send the debug string to another script, and let it decide parsing.

in the orignial example that Meade and I both wrote in different thread, we couldn't eliminate the string, but we could kill all extra the bytcode for the if statement and it's associated reference to DEBUG and the bytecode for the say, which presumably is more than a call to a seperate function to handle it all. it could probably be reduced farther with a well placed global or two.

you are absolutley right about tight loops, if a block is being called inside a loop far more consistently than outside it it may be better to write it all out, at least for the loop. but that seems like a pretty rare case to be using it in both... any block in a loop is a single block (if you call the same set of actions more than once in a loop, the loop could probably use rewritting)

if I were going to offload all Debugs to a seperate script I'd probably use the folowing

//--eleminates bytecode overhead for each variable in link messages except the debug code
fDebug( integer vIntDebug ){
llMessageLinked( LINK_THIS, vIntDebug, "DEBUG", "" );
//-- key could be added for more complex debugging messages and variable handling
}

and call it with
fDebug( <some number> );

and the debug handler script would conatin
list gLstCodes = [<code numbers paired with messages> ];

link_message( integer vIntNull, integer vIntCode, string vStrMessage, key vKeyExtendedInfo ){
if ("DEBUG" == vStrMessage){
//-- procces code to message and ouput to llOwnerSay
}
}

several variations are possible.... and I'd only use something like this if it was intended to be left in, for instances where I intend to remove all debug commands before offering it up, I'd just use the function, and not even bother with a test (or as I often do, just use owner says, and remove them later.)
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
1 2