Jump to content

LSL profiling


animats
 Share

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

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

Recommended Posts

I've tried it, but I can't say I ever really used it. llScriptProfiler keeps track of the absolute high water mark of memory usage. At least in my experience, that number (llGetSPMaxMem) will be the same as llGetUsedMemory unless the script does something to trigger garbage collection.

It would be great if somebody could tell us more about gc in Mono. By trial and error I found I could shrink llGetUsedMemory by calling llSetMemoryLimit to a value closer to what I know to be the actual memory use after freeing a bunch of junk, then setting it wide open again. I have no idea if that's doing it right. (I sure wouldn't want to do anything else between those llSetMemoryLimit calls.)

Link to comment
Share on other sites

The Mono garbage collector is conclusively mysterious.

When exactly it chooses to run is unpredictable, though at least one reliable moment is when the script is about to stack-heap collide. When a script has effectively run out of memory, GC will run and if there's still no memory available, the script will announce the problem and die. Some people also think that llSleep is one moment when GC might be triggered, but I can't comment one way or another.

Unrelated to garbage collection, LSL code has "yield points" in many places such as loops, where the current memory use is checked. If the memory usage goes above 64KB between yield points, no errors (and maybe GC) will trigger. One source but not all the info: https://www.youtube.com/watch?v=QGneU76KuSY&feature=youtu.be&t=1282

Some (historical) reading material:

The basic concept of any GC I know of (not many) is the same in all of them. "Does anything refer to this location in memory? If not, free it." Modern GCs are more sophisticated than that, allowing for different kinds of garbage collection (more frequent, predictable, and handling different types of data differently).

 

Edited by Wulfie Reanimator
  • Thanks 2
Link to comment
Share on other sites

4 hours ago, Qie Niangao said:

I've tried it, but I can't say I ever really used it. llScriptProfiler keeps track of the absolute high water mark of memory usage. At least in my experience, that number (llGetSPMaxMem) will be the same as llGetUsedMemory unless the script does something to trigger garbage collection.

It would be great if somebody could tell us more about gc in Mono. By trial and error I found I could shrink llGetUsedMemory by calling llSetMemoryLimit to a value closer to what I know to be the actual memory use after freeing a bunch of junk, then setting it wide open again. I have no idea if that's doing it right. (I sure wouldn't want to do anything else between those llSetMemoryLimit calls.)

llgetusedmemory is very different of LlGetSPMaxMemory when you compile your script in mono

Because  LlGetSPMaxMemory reports the max of memory between two times :

( when you have declared llscriptprofile to true and when you have declared llscriptprofile to false )

 

Nevertheless , all these functions ( llgetusedmemory , llfreemory , llgestspmaxmemory  etc .. ) about memory are often useless in practice because

even whi th their report , there is no wokround solution

Link to comment
Share on other sites

8 minutes ago, Miranda Umino said:

llgetusedmemory is very different of LlGetSPMaxMemory when you compile your script in mono

Because  LlGetSPMaxMemory reports the max of memory between two times :

( when you have declared llscriptprofile to true and when you have declared llscriptprofile to false )

Hmmm. If no garbage collection happens, doesn't llGetUsedMemory() return the same value when called at the point you'd turn off llScriptProfiler()? Maybe I'm missing something.

3 minutes ago, Miranda Umino said:

there is no wokround solution

I guess that depends on why one is calling the functions.

If I'm just making sure during development that there's enough padding that the script won't blow up, then the workaround is simply to offload memory to another script or otherwise change things to use less memory in the script.

At runtime, I use llGetFreeMemory() in order to know how many key-value pairs I dare read in one gulp from Experience persistent store, for example. That's why I force gc: to find out how much I can buffer after freeing the previous batch.

Link to comment
Share on other sites

59 minutes ago, Qie Niangao said:

1) Hmmm. If no garbage collection happens, doesn't llGetUsedMemory() return the same value when called at the point you'd turn off llScriptProfiler()? Maybe I'm missing something.

I guess that depends on why one is calling the functions.

2) If I'm just making sure during development that there's enough padding that the script won't blow up, then the workaround is simply to offload memory to another script or otherwise change things to use less memory in the script.

At runtime, I use llGetFreeMemory() in order to know how many key-value pairs I dare read in one gulp from Experience persistent store, for example. That's why I force gc: to find out how much I can buffer after freeing the previous batch.

answer to 1)

No .. the script can have a duration of several hours .. If the memory is fragmented ( with holes ) , llgetusedmemory will return the max with the holes

With  llGetSPMaxMemory , it will be only between when you have started to setup true  with llsetProfile and the when you have setup false llsetprofile  . So it allows you to verify in a range of seconds  ,and there will few probabilities to havea memory fragmented between the time 

answer 2)  i have given up llGetfreememory . I am not sure to understand your instance with "experience persistent store" . llDataSizeKeyValue returns the amount memory you have chosen , no ? And the memory for "experience store" is different  ( and very small) from memory script , no ?

Edited by Miranda Umino
Link to comment
Share on other sites

Afraid I still don't follow.

With 1), I can call llGetUsedMemory after a brief interval, in the same place I would turn llScriptProfiler off, and I'd expect the same results I'd get from llGetSPMaxMemory. I'm not seeing when this wouldn't suffice. (I mean, I could wait around and call llGetSPMaxMemory later and get the value from back when the profiler was on, but I could just save the value from llGetUsedMemory, too.)

With 2), llDataSizeKeyValue returns the size of the experience's entire persistent store which can be pretty huge by LSL standards (like 132 MB, if I recall correctly), and each pair can be 1011 bytes for the key and 4KB for the value. For a large experience, it's common to fetch some llKeysKeyValue() and use the result in a sequence of llReadKeyValue() calls, so it's important to watch how much space remains to know whether to continue reading or to process the batch before flushing the buffer and continuing. (I guess for some applications one could do it a pair at a time, but I'm dealing with real network turnaround delays).

Link to comment
Share on other sites

38 minutes ago, Qie Niangao said:

With 1), I can call llGetUsedMemory after a brief interval, in the same place I would turn llScriptProfiler off, and I'd expect the same results I'd get from llGetSPMaxMemory. I'm not seeing when this wouldn't suffice. (I mean, I could wait around and call llGetSPMaxMemory later and get the value from back when the profiler was on, but I could just save the value from llGetUsedMemory, too.)

Imagine the memory use between profiling start and end as a bell-curve. SPMaxMemory will report the highest point of the curve, UsedMemory will be the current (low) amount.

Now imagine the memory use as a linear decrease. SPMaxMemory will return the memory use at the beginning, UsedMemory will report the memory use at the end.

Now imagine a flat line, or an increase that levels out (GC doesn't run or at least clean any of that code). SPMaxMemory and UsedMemory will report the same amount of memory use.

Edited by Wulfie Reanimator
  • Thanks 1
Link to comment
Share on other sites

Ah, maybe I get it. Thanks. Yes definitely, if gc runs, all bets are off. That's why I started with "If no garbage collection happens, ..." 

Maybe other things trigger it, but I really haven't seen gc run unless the script is at the memory limit -- either because usage (including garbage) grew, or because the limit shrank. In my experience, then, memory use (including garbage) monotonically increases until gc.

So I guess script profiling could reveal that gc ran, if SPMaxMem is found to be larger than UsedMem, so yeah, that might be useful to know.

Link to comment
Share on other sites

On 7/10/2019 at 5:38 PM, Qie Niangao said:

Afraid I still don't follow.

With 1), I can call llGetUsedMemory after a brief interval, in the same place I would turn llScriptProfiler off, and I'd expect the same results I'd get from llGetSPMaxMemory. I'm not seeing when this wouldn't suffice. (I mean, I could wait around and call llGetSPMaxMemory later and get the value from back when the profiler was on, but I could just save the value from llGetUsedMemory, too.)

With 2), llDataSizeKeyValue returns the size of the experience's entire persistent store which can be pretty huge by LSL standards (like 132 MB, if I recall correctly), and each pair can be 1011 bytes for the key and 4KB for the value. For a large experience, it's common to fetch some llKeysKeyValue() and use the result in a sequence of llReadKeyValue() calls, so it's important to watch how much space remains to know whether to continue reading or to process the batch before flushing the buffer and continuing. (I guess for some applications one could do it a pair at a time, but I'm dealing with real network turnaround delays).

i am sorry but  from where you have seen there is 132 mb in expériences ?

Maube you make a mess with ALL the datas of the sim  : and it s few compared to the amount of memory of a full sim   : a simple user who uses an expérience is limited to some kilobytes 

You talk about http://wiki.secondlife.com/wiki/LlKeysKeyValue

But i read : "The length of the returned list is limited to 4097 characters "

It s  the list who is limited to 4097 and not an element of the list . 

So , i don t understand your post and the link with the memory script usage

Link to comment
Share on other sites

When I call llDataSizeKeyValue() from a script compiled to my Experience, it returns about 132 M as the second value ("quota") in the cdl string. I've been assuming that all Experiences have that same capacity.

An Experience's persistent store is not local to the sim; it's available simultaneously to scripts running on all sims.

llKeysKeyValue provides a way of fetching a sequential batch of the data in the store. It returns a list of keys that can then be used to then read their associated values. The return key list can hold up to 4K characters, but the length of a key can vary widely, so that could correspond to over a thousand rows or as few as four.

The store is completely separate from script memory, but scripts that interact with the store at scale are going to need to carefully manage memory usage. It's sorta analogous to making sure there's always free memory when reading in a batch of Notecards -- but with a potentially huge number of (writable) Notecards.

(Coincidentally, like an Experience's persistent store,  a Notecard too is not local to the sim. Scripts can read it grid-wide by referencing its UUID rather than using its name in an object's inventory.)

  • Thanks 1
Link to comment
Share on other sites

2 minutes ago, Qie Niangao said:

...

(Coincidentally, like an Experience's persistent store,  a Notecard too is not local to the sim. Scripts can read it grid-wide by referencing its UUID rather than using its name in an object's inventory.)

Oh! Does that mean I can keep a notecard in my inventory and have scripts read it from there?

Link to comment
Share on other sites

1 minute ago, KT Kingsley said:

Oh! Does that mean I can keep a notecard in my inventory and have scripts read it from there?

am going to try this myself, as I never knew about it

it opens up all kinds of possibilities for a single black/white list notecard for devices.  Up until now I have been putting a copy of the notecard in every device, or using messaging to communicate with a black/white list device controller

 

Link to comment
Share on other sites

5 minutes ago, KT Kingsley said:

Oh! Does that mean I can keep a notecard in my inventory and have scripts read it from there?

I think so. You can get its UUID while in your inventory, right? But also keep in mind that you can't edit the notecard because it will get a new UUID when saved, so the UUID-referencing scripts won't see updates. That's one big win for Experience persistent store: It's writable shared memory -- as much communication vehicle as data store.

  • Thanks 2
Link to comment
Share on other sites

Just now, Qie Niangao said:

I think so. You can get its UUID while in your inventory, right? But also keep in mind that you can't edit the notecard because it will get a new UUID when saved, so the UUID-referencing scripts won't see updates

ah! yes. bummer!

might still be useful tho in some fixed/limited scenarios.   So still thanks!  

  • Like 1
Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 1750 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...