Jump to content

Stack-Heap Collision


Kayaker Magic
 Share

You are about to reply to a thread that has been inactive for 1473 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

I started adding new features to one of my favorite scripts (around 1000 lines of code). I converted some of the code to functions for re-use, I added new lists and managed them. Before I finished adding all the new features, I got “Stack-Heap Collision”. The script runs for a few seconds, collects some data in the lists and then runs out of memory.

So what am I going to be able to do? Does this mean I was pushing the edge of the memory limits before and now I have to give up on adding the new features?

 



Link to comment
Share on other sites

Yes and no. You reached the limit - but there are things you can do

  • optimize your code. Do you really need all the information you keep in the memory? Can you optimize your code?
  • distribute the data and possibly logic across several scripts
  • handle big amounts of data and computation on a webserver
Link to comment
Share on other sites

another thing to consider is that while reusable code is nice, functions are bloated in LSL, ESPECIALLY ones that are passed lists (LSL is pass by value, meaning the variable is duplicated if passed as a parameter to a user function). it's better to inline code that is only used in one place (save the function version for reference to use elsewhere), and sometimes even if it's used in multiple spots (this generally requires testing, but if it's passing lots of variables, it often works out as more memory used)

if you are attached to the reusable functions you could move some out to another script, and communicate via link_messages or even prim property changes but unless you use polling loops (not recommended) to catch the return values you'll have to catch the results in a new event. that works fine for some functions that don't need an immediate return (updating stored values), but doesn't always work well for things you need an immediate or complex response from.

Link to comment
Share on other sites

Besides re-usability, I also use functions for code documentation. I'm horrified to find myself considering taking code that is nicely compartmented into functions with meaningful names (setup, start_dialog, move_fwd, etc) and moving this code into the events that used to call them (on_rez, touch_start, timer, etc.). This is not a good thing IMHO.

 



Link to comment
Share on other sites

Void makes an excellent point about variables being passed by value, not reference.

One option may be to keep the functions but not pass the information to it. Rather have the function access a global variable, especially for lists. If I understand LSL correctly, with this method you are not using up memory making a copy of a large list just to pass it to a function.

- Clarke

Link to comment
Share on other sites

 Unfortunately, I was already storing all lists in globals and the functions are called with no or only a few arguments (like a new position or a dialog message string). I'm starting to warm to the idea of splitting my script into several scripts and using llMessageLinked to communicate. But talk about "send by value" issues, llMessageLinked can only "send by string"! So I'll have to parse the string, find out what value is changing and convert vectors and floats back from strings on every message. If I design the protocol to only send messages when things change, then the "main" script will still work the way that it used to. A "data" script will keep the new lists I'm adding and send infrequent updates to the main script. And I can add a third script to handle the dialog box and other user interface issues to save space for more data in the data script.

  Is it true that a llListen in one script does not cause the listen events in other scripts to get copies of all the resulting messages? The Wiki implies that the effect is local to the calling script, but doesn't specifically say what happens with multiple scripts in a single prim.

  Of cource I was trying to keep my script count down for future script limitations that LL is considering. I have to give up on that one now.

 

 

Link to comment
Share on other sites

the code can still mostly self document if you re-name any default variables, and you can always throw in a set of extra brackets and a comment to note insertion of functions inline.

as for messaging, you don't HAVE to rely on link messages....  prim properties can often be just as effective, and let you send more specific data types directly.... vector, float  and key on hidden faces with color alpha and texture. rotation within child prims that are hidden, etc

Link to comment
Share on other sites

If you need to send a list in a message, you can use llList2CSV or llDumpList2String.

Unfortunately,  the lsl functions that go the other way, llCSV2List and llParseString2List, produce a list of strings.

list_cast  solves the problem by converting each type into what it appears to be.

list_cast can accurately recover the original type unless the original type was string and the contents are all digits (and possibly a .).  There is/was another set of functions whose name escapes me that handles even that case.

 

Link to comment
Share on other sites

Store varaiables in prim properties unused is in my opinion something to avoid if we don t need to store permanently .

 

Firstly it s slower than LINK_MESSAGES;

secondly all the world is warned by the modification of the prim so it increases the general sim lag . Informations of change of properties are broadcasted to any avatars .

 

 

default{    touch_start(integer total_number)    {                integer i = 10000;        key k1 = llGetKey();        key k2 = llGetOwner();        float x = llGetTime();        while ( ~ --i )        {            llMessageLinked(LINK_SET, 1000,"", k1);            llMessageLinked(LINK_SET, 1000,"", k2);        }        llOwnerSay((string)(llGetTime()-x));                        i = 10000;        x = llGetTime();        while ( ~ --i )        {            llSetLinkPrimitiveParamsFast(LINK_SET,                 [ PRIM_TEXTURE, 1, k1, ZERO_VECTOR, ZERO_VECTOR, 0.0 ] );            llSetLinkPrimitiveParamsFast(LINK_SET,                 [ PRIM_TEXTURE, 1, k2, ZERO_VECTOR, ZERO_VECTOR, 0.0 ] );                        }        llOwnerSay((string)(llGetTime()-x));            }}[12:55] Object: 9.774347 time for linked_messages[12:56] Object: 109.367800 time for set properties

 

.

Link to comment
Share on other sites

for keys, no, not much use, for vectors and rotations, there is precision loss in link messages (or extreme oeverhead in lossless conversion) and conversion overhead on both ends. for multiple datatypes there are some parameters that are very useful. it's also the only feasible way to return data from an external script without exiting the current event (although like I said, not recommended). update issues may not exist depending on the nature of the build, and are greatly mitigated by low frequency of use. it also avoids clogging link message queues if those are under high volume from other scripts.

I never meant to imply though that those methods are more efficient, just that they are options that have some unique benefits, and also unique drawbacks.

PS
textures set by script don't trigger changed_texture, so it probably wouldn't be a good idea to use that. that and other oddities of the changed event (most likely catcher for messaging this way) are not noted in any of the wikis, but there's a few open jiras.... the fix for that one caused the server code rollback that doomed us to no lsl updates untill the current system of rollouts was adopted.

ETA:
yes that means I screwed up in my reference to using texture to pass keys

Link to comment
Share on other sites

  • 8 years later...

Not exactly sure what you're asking, but it's not at all surprising that a stack-heap collision happens as the script runs a while, not "to begin with" -- it's simply using more memory than the script's limit. If this is your own script, you have some debugging to do. If it's somebody else's and you can't see the source, there's not a lot you can do. If the containing object is modifiable, you could try Build/Scripts/"Recompile scripts (Mono)" on the off chance that it was previously compiled "(LSL)" which usually allows less memory capacity. (I guess you could try it the other way, too, on the very remote chance the scripter used llSetMemoryLimit too low -- a no-op in the "LSL" compiler.)

If this doesn't help, you'll probably need to provide a bunch more detail about what exactly this script is, when the problem arises, etc.

Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 1473 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...