Jump to content

llGetAgentList caveat


Innula Zenovka
 Share

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

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

Recommended Posts

Maybe I'm the only one who didn't realise this, but people should be aware that llGetAgentList can be dangerous in some circumstances.

It returns up to 100 keys, and there's no way of limiting this.   And, as Haravikk Mistral, who started a jira about it (SRC-371), comments:

  •  while it's incredibly unlikely, if the function is able to return potentially 100 results than that's at least 6kb of memory, far more likely ~10kb with list overhead, which means you need 20kb (30kb to be safe) to actually manipulate such a list…

I came across it  while I was planning out a script for an attachment which, since the script does a lot of other things too, would probably have blown up if it detected more than ~30 people on the sim, and that's obviously a more realistic danger.

There's some discussion, and background, over at SLU.

Link to comment
Share on other sites

That had not occurred to me either, and I just released updates to my entire product line with scripts that use it.  I tested with 25 people on the sim, but the implication of what happens in an even busier place did not occur to me.

Thanks for the heads up.

ETA:  I got lucky, the script I have calling it has quite a bit of free memory. 

Link to comment
Share on other sites

My process (accidentally) for using llGetAgentList so far has to been to test with llGetAgentCount to start (if the sim has more than 20 avs, llGetAgentList doesn't fire).

Mostly because the purpose I needed it for, I only need those numbers if the sim is on the quiet side. If you absolutely needed a list, I guess you could go 'old-school' and run a sensor instead.

Too cludgy? :P Does kind of undermine the purpose of the new commands.

 

Link to comment
Share on other sites

Wrong problem :

firstly 10kb is few when your script is limited to 64kb

secondly there is absolutely no reason tu compile new scripts with new functons in LSO

thirstly you are not obliged to keep the 10kb  . You need them only when you parse the answer of llgetagentlist . So the memory will be freed after the next event . Save only the keys who interest you.

fourthly there are other finctions as http://wiki.secondlife.com/wiki/LlGetParcelPrimOwners who may return 100 values .

In fact , its a strided list , so llGetParcelPrimOwners  may return 100 keys and 100 integers , so 1.5 X more than llGetAgentList  . Nobody has complained about this . Nobody has requested about llGetParcelPrimOwners to limit the size of returned datas. And its more frequent in-world to have 100  different prim-owners in a sim ( for instance in a sandbox , or in a group ) . To have 100 avatars in a sim is less frequent

llCastray may return a strided list of 256  elements , so , with additional flags 256 keys , 256 postion vectors , 256  integer , and 256 normal vectors . It s s something around 40kb

llGetLinkPrimitiveParams may return more than 10kb if you call as llGetLinkPrimitiveParams(LINK_THIS,, [options, PRIM_LINK_TARGET , link2, option2, PRIM_LINK_TARGET, link3, options3 .. PRIM_LINK_TARGET,link255, option255] ) with a 256 prim linked

Only with 4 prims a call as 

l = llGetLinkPrimitiveParams(LINK_THIS, [
PRIM_TEXTURE, ALL_SIDES,
PRIM_LINK_TARGET , 2, PRIM_TEXTURE, ALL_SIDES,
PRIM_LINK_TARGET , 3, PRIM_TEXTURE, ALL_SIDES,
PRIM_LINK_TARGET , 4, PRIM_TEXTURE, ALL_SIDES] );

may take 10kb . It depends of the number of faces of your prims  ( sphere with one face or mesh / tortured torus with 8 faces)

Firthly , you have some additional filters to llgetegentlist to limit to a parcel . How many sims have 100 avatars on . And how many parcels have 100 avatars on ? I don t see a lot of  them in-world

To forbid and to limit scripters are bad .  This limitation to 20 is not meaningful : Which avatars  will be returned ? The nearest of the prim ? It s long and costly for the sim .  The fisrtsly laphabetically named agents ? Some random keys ? It s useless for the scripter to have 20 random agents in the region. And more stupid  if you want to limit to 20 the results of llGetAgentList is the absence of pagination.

Something like  list llGetAgentListinteger scope, list options, integer page );

 

Why to have some keys about a subset of agents , when there is no rule to determine this subset , and there is no way to switch from a subset to an another subset ? I don t see any interest

But even if some pagination would exist , the datas won t be coherent : if Linden Lab adds some pagination to this function , how will be coherent the datas returned between the call for the first page and the call of the second page if people enter and leave in the sim  between the two moments ?

 

 

 

 

Link to comment
Share on other sites

 All I was saying, Miranda, is that when you use llGetAgentList there are circumstances in which it's going to use quite a considerable amount of memory -- potentially a lot more than would llSensor, which I was using it as a replacement for -- and it's as well to be aware of this.    

Of course I'm not saying don't use it -- all I'm saying is that if you're using it in a long and complicated script that's storing other things as well, which is the case with the script I'm working on,  it's good to keep in mind that you may find yourself briefly manipulating a much longer list than you might have been expecting, or than you've encountered in testing.   That's all.

 

Link to comment
Share on other sites

Innula's observation and warning were much appreciated by me.   We should never plan our scripts on the best case scenario.  There is very little chance of a sim with 100 Avatars.  It is still theoretically POSSIBLE, and therefore we need to take it into consideration in our memory usage planning.

As for the rest of the discussion about other functions returning a great deal of data . . .um . .so?  You need to plan for them too if you use those functions.

 

Link to comment
Share on other sites

Nevertheless the solution told by this JIRA is not a solution ... Neither exact , neither satistfying

 

  • The "solution"  doesnt solve  some memory issues caused by other functions llGetParcelPrimOwners, llCastray , llGetLinkPrimitiveParams and in a general way , every functions returning a list

 


  • The "solution"  doesn t give a way to have some exploitable, functionnal , useful  datas . What could i do with 20 random keys of agents present in my sim if there are 100 agents ? 

For instance , if i  want to use llgetagentlist to check  who are the agents in my sim who meet a particular criteria ,  how could i do it with a truncated list ? How i do for instance to know all the avatars with an agentsize below of 1m , if the list returened by llgetagentlist is truncated ?

Second instance , this function has been required , for instance to check who has entered in a sim and who has left : how could i know it with a truncated list ?

 

 

 Of course , i agree to secure our scripts . But this solution is not helpful.

If it was possible to use some callbacks of user defeined functions it would be nicer.

For instance , with a callback who returns always a boolean , and have the key of agent in parameter

integer mycallback_has_no_display_name( key avatar){       string name = llGetDisplayName(avatar);    if ((name == "???") || (name == ""))             return TRUE;    else            return FALSE;}llRegisterCallback("mycallback_has_no_display_name");list results = llGetAgentList(AGENT_LIST_REGION, "mycallback_has_no_display_name" );And internally llgetagentlist applies our callback for each element of the list . The list "results" could contain only the avatar with no display names. 

 

Link to comment
Share on other sites

100 keys take 3600 bytes (100x36), with list overhead prolly would take 5K. An efficient script would need about 10K for processing, no more than that. If don't have 10K available, make another module that would do only large list storage/processing and talk to the main script via linked msgs.

Link to comment
Share on other sites

I agree the jira solution isn't a particularly good one since, as you say, there's little point in truncating the list unless you can specify to the sim how you want it ordered.   If that were possible, it would be great -- tell me the 30 nearest avatars, or tell me the 10 avatars who've been here longest -- but that looks easier said than done.

I just quoted the jira because it explained why the  long lists are problem.   Which, under some circumstances, they certainly are, if you 're not expecting them.

Link to comment
Share on other sites

Maybe you may try llList2List before to store the result of llgetagentlist in a variable .

Logically you will have more than 64kb but maybe it doesn t give the time to the memory manager to crash your script .

Probably it s very unsafe . I remember may times some scripts crashing when we use as it

I am just giving this instance of script , but i don t hint it . It s not a solution

 

list keys;list dummy;integer half;default{    link_message(integer sender, integer num, string s, key k)    {        if ( num  == 1000 )        {            llOwnerSay("======= 1st Half ========");            llScriptProfiler(PROFILE_SCRIPT_MEMORY);            llOwnerSay("before="+(string)llGetUsedMemory());             half = llGetRegionAgentCount() / 2;            keys = llList2List( llGetAgentList(AGENT_LIST_REGION, []) , 1, half );            llOwnerSay("after="+(string)llGetUsedMemory());             llOwnerSay((string)llGetListLength(keys)+ " keys");                         llScriptProfiler(PROFILE_NONE);            llOwnerSay("This script used at most " + (string)llGetSPMaxMemory() + " bytes of memory .") ;            keys = [];            llMessageLinked(LINK_THIS, 1001, "", "" );                      }        else if ( num  == 1001 )        {            llOwnerSay("======= 2nd Half ========");                        llScriptProfiler(PROFILE_SCRIPT_MEMORY);            llOwnerSay("before="+(string)llGetUsedMemory());             half = llGetRegionAgentCount() / 2;            keys = llList2List( llGetAgentList(AGENT_LIST_REGION, []) , half + 1, -1);            llOwnerSay("after="+(string)llGetUsedMemory());            llOwnerSay((string)llGetListLength(keys)+ " keys");                         llScriptProfiler(PROFILE_NONE);            llOwnerSay("This script used at most " + (string)llGetSPMaxMemory() + " bytes of memory .") ;            keys = [];            llMessageLinked(LINK_THIS, 1002, "", "" );                      }                else if ( num  == 1002 )        {            llOwnerSay("======= Full  ========");                        llScriptProfiler(PROFILE_SCRIPT_MEMORY);            llOwnerSay("before="+(string)llGetUsedMemory());             keys = llList2List( llGetAgentList(AGENT_LIST_REGION, []) , 1, -1 );            llOwnerSay("after="+(string)llGetUsedMemory());            llOwnerSay((string)llGetListLength(keys)+ " keys");            llScriptProfiler(PROFILE_NONE);            llOwnerSay("This script used at most " + (string)llGetSPMaxMemory() + " bytes of memory .") ;               keys = [];                 }    }    touch_end(integer n)    {        llMessageLinked(LINK_THIS, 1000, "", "" );      }}

 

WIth a 70 avtars sims :

 

sometimes it s ok :

[11:50] Object: ======= 1st Half ========
[11:50] Object: before=7036
[11:50] Object: after=11220
[11:50] Object: 39 keys
[11:50] Object: This script used at most 11220 bytes of memory .
[11:50] Object: ======= 2nd Half ========
[11:50] Object: before=7036
[11:50] Object: after=11016
[11:50] Object: 38 keys
[11:50] Object: This script used at most 11086 bytes of memory .
[11:50] Object: ======= Full ========
[11:50] Object: before=7036
[11:50] Object: after=15200
[11:50] Object: 77 keys
[11:50] Object: This script used at most 15200 bytes of memory .

 

sometimes it s dnagerous 

[11:51] Object: ======= 1st Half ========
[11:51] Object: before=7036
[11:51] Object: after=11310
[11:51] Object: 41 keys
[11:51] Object: This script used at most 11380 bytes of memory .
[11:51] Object: ======= 2nd Half ========
[11:51] Object: before=7036
[11:51] Object: after=15660
[11:51] Object: 39 keys
[11:51] Object: This script used at most 15660 bytes of memory .
[11:51] Object: ======= Full ========
[11:51] Object: before=7036
[11:51] Object: after=15388
[11:51] Object: 80 keys
[11:51] Object: This script used at most 15458 bytes of memory .

 

It seems be important to leave the event or to wait a few moment between 2 calls two llgetagentlist to have the memory freed 

Link to comment
Share on other sites

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