Jump to content

llRemoteLoadScriptPin - Delay (Solved!?)


Wandering Soulstar
You are about to reply to a thread that has been inactive for 2340 days.

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

Recommended Posts

Hi All,

 

Another of my questions today :-) ... seriously thanks to all for your help so far!

In the Wiki it states for the llRemoteLoadScriptPin function that:

  • This function causes the script to sleep for 3.0 seconds.

Is this delay effected, as I assume, in the script that is calling the function? Or is it the script being loaded that is delayed?

 

Thanks!

Wanda

 

Link to post
Share on other sites

<sigh> was afraid of that ....

 

May have to go back to the drawing board on my design.

 

For whoever might wonder where all my questions are from, I am building a HUD to be used by builders, where the core design is that prims being built can contain multiple scripts that execute certain function (Texture Settings, sizing, alignment, etc). The HUD has the repository of these scripts and they can be delivered to the Prims being worked on. One of the functions I want is to be able to update versions of the scripts in the repository, or add new ones, and have these delivered to the active prims, hence my question on the delay ... in a decent size build this could result in a major delay as the script(s) are delivered to 10's or 100's of prims.

Link to post
Share on other sites

You may have sevarl scripts who call llRemoteLoadScriptPin  at the same time .

 

For instance , 

you have one main controller script , who callls llMessageLinked to the other scripts with a parameter

The other scripts who receive link_message and call llRemoteLoadScriptPin  : the parameter sent by the controller informs which "passive" script you want to remoteload

 

In this case , your effective delay will be 3 seconds / number of scripts who call llremoteLoadScriptPin

Link to post
Share on other sites

Just thinking out loud here, but: could use llRemoteLoadScriptPin to deliver both the intended payload script and a script that further distributes that payload to another target. Should be possible from within one target to figure out which would be the next target -- either in a flat sequence or a tree of self-spreading scripts.

I think a single script could spread itself this way, using a start parameter to avoid doing it when merely reset. (Otherwise, a flat sequence would be just as slow as doing it from a central prim; slightly slower, in fact.)

Link to post
Share on other sites

You don t need to have the same number of giver scripts as the number  of given scripts.

If you have 10 givers and 100 given , it will divide your time by 10 .

Not neglectible

Extreme ? Maybe ... As much as it is to give 100 scripts ...

 

 

Question ? is it the same script given 100 times ?

In this case , the script given can give itself too .

The recursivity will  make replicate scripts in few steps : 2,4,8,16 etc ..

 

Link to post
Share on other sites

Thanks for the ideas, but do not quite think either solution is possible based on my current design structure, and changing that structure means almost starting over :-).

What I mean is that I have a central script in the HUD, this is the only script in the HUD that listens to the 'outside world' and the only one that communicates with it. Within each building prim there is a control script as well, but it only talks to the HUD (one channel) and listens to the HUD (another channel). The HUD does not keep track of the prim controllers that are out there, particularly because the user could be building in different locations and the HUD needs to work against the scripts in all locations independently.

When the HUD goes to deliver the scripts, it sends out a call and then, as the prims respond, it sends them the script. Thinking of it, I could use the multiple distribution script scenario, with the HUD simply looping through a collection of deliverers, but the idea of having 100 scripts in the HUD is a bit unnerving. And as you can see the idea of having the target prim replicate the scripts on to the 'next' prim would not work, apart from a change in design; how would the code determine which is the next prim? There could easily be more than 100 prims in range all with exactly the same scripts in them.

<Edit>

Just thinking of the multiple deliverers ... I could have them loaded into the HUD, but not running and only start them as needed to deliver and then shut them down afterwards .. at least would keep general memory from being over burdened

Link to post
Share on other sites

It's difficult to guess exactly what you need without looking at a complete specification of the problem.

 

However, I'll venture a possible solution if it's a matter of just distributing and activating one script among a number of rezzed prims: Have the script in the inventory prim to begin with, but have only a listen() event handler in the default state and, when triggered, have it switch to the "working" state. You could also toggle between the default and working states the same way, effectively turning "on" and "off" the script. 

 

ETA: There are two ways to toggle back to default()- state default; and llResetScript();. They both will clear the event queue but the second also reinitializes your global variables and clears the timer.

Link to post
Share on other sites

LepreKhaun,

 

What I have is (in simplified form):

  • One HUD Script
  • N Building Prims each with a controler script and N worker scripts. Only one worker script is active at any one time and these scripts may or may not have been written by me.

The Scenario is that the HUD receives an updated, or new, worker script and needs to deliver this script to the Building Prims. The controller script is listening to the HUD. The basic flow is:

  1. HUD sends out a call saying 'I have a/some' script(s) to deliver
  2. The controllers in the Building Prims respond saying 'I'm here and my Key is ...'
  3. As the HUD receives the response from a Buildng Prim it sends the worker script (not running)

As you can see the issue is the 3 sec delay caused by llRemoteLoadScriptPin. In a building project it would not be unheard of to have more than 100 building prims, and having it take 5 minutes to distribute one script is just not workable.

 

Link to post
Share on other sites


Wandering Soulstar wrote:

Just thinking of the multiple deliverers ... I could have them loaded into the HUD, but not running and only start them as needed to deliver and then shut them down afterwards .. at least would keep general memory from being over burdened

It may be a good thing to do, but it doesn't affect memory use. Every script in the contents of an object rezzed on the sim must be resident in that sim's script engine, whether it's set running or not. That's because there's simply nowhere else for the script's state to exist.

So here's another option: Instead of pushing the updated script directly from the HUD, have the HUD rez a "script update relay" object that it will use to pass on the scripts to the intended target prims. The only advantage of this is that the relay object can have oodles of scripts inside to simultaneously llRemoteLoadScriptPin out to the targets, but the relay object doesn't have to be rezzed on the sim except on those rare occasions when there's an update to distribute.

I should caution, however, that I'm unsure of the system design, now that it's been explained. I'm particularly concerned about the HUD listening to hundreds of target prims that will all respond to the HUD's call: I'm thinking all those simultaneous responses will overrun the HUD script's event buffer.

Link to post
Share on other sites

Qie,

I did not think that a script set to not running was using available script memory ... does though make some sense if the state of the script when it was stopped is maintained. How though is that different from an object (prim) containing the scripts that is inside another object?

As to the buffer issue .. I know, am wondering about that myself, and until I get the HUD past initial coding and can do a stress test on it (my next building project) I will not know.

Link to post
Share on other sites


Wandering Soulstar wrote:

Qie,

I did not think that a script set to not running was using available script memory ... does though make some sense if the state of the script when it was stopped is maintained. How though is that different from an object (prim) containing the scripts that is inside another object?

As to the buffer issue .. I know, am wondering about that myself, and until I get the HUD past initial coding and can do a stress test on it (my next building project) I will not know.

Difference is that the scripts inside an object's inventory have no state; they'll start from default state_entry if rezzed somewhere they can run, and until then they're just compiled code stored in a central server's database. (I can't think of any theoretical reason that sim-resident not-running scripts complete with state couldn't be shunted off to the same database instead of residing in sim memory, but they aren't. On the plus side, having them all in sim memory makes them quick and cheap to turn on and off.)

I wanted to raise the event buffer issue in case somebody had a suggestion. Off the top of my head, I'd just delay the responses for random amounts of time and hope for the best, but there may be some standard practice that's sure to always work for any number of responses.

Link to post
Share on other sites

As you can see the issue is the 3 sec delay caused by llRemoteLoadScriptPin. 

In a building project it would not be unheard of to have more than 100 building prims,

and having it take 5 minutes to distribute one script is just not workable.

 No ,  it won t be 3 s  * 100 = 5 minutes  :

it will be around 3 s * LN(100) / LN( 2 ) = 20 seconds

Link to post
Share on other sites

yes , logarithmic .

 

Indeed :

- at the start, you have your hud who wontains the new script , and the list of keys of objects you want updated

- aat the iteration 1 , you send the script to one object , but this object can too work in parallelism with your hud to send the new nscript to the others , so you send too the half of list of keys

- iteration   2 , your hud send the half of the half of initial list to an another object  and the new script ; the first object sends too one half of half of the initial list to an another object ; and as it has got now the new script , it  gives it to an another object . so 2 objects will be updated at this time . as the last step , they can work in parallelism with the hud and the 1st object tosend the new script too to other objects

- iteration 3, your hud continues to work with the 1/8th of the iitial list . the 3 other objects do the same . so 4 objects will be updated at this step . Total of objects with the new script is 4 + 2 + 1 = 7

- iteration 4 : 8 objects will be updated at this step ; Total of objects with the new script is 8 + 4 + 2 + 1 = 15

- iteration 5 : 16 objects will be updated at this step ; Total of objects with the new script is 31

- iteration 6 : 32 objects will be updated at this step ; Total of objects with the new script is 63

- iteration 7 : 64 objects will be updated at this step ; Total of objects with the new script is 127

 

7 steps are enough to update your 100 objects ., so 21 secondes are caused by the delay .

In a general formule , total time of the delay is 3 secondes * LN base 2 ( 100) .

Of course in practice there will be some other seconds by overhead , but you will be very far from 5 minutes

 

 

Link to post
Share on other sites


Rolig Loon wrote:

Natural log would be my guess.   LN (x) = 2.30258 Log10(x).  But don't ask me why it's here.  :smileyindifferent:

Rather the logarithm based on the number two

log(1024)/log(2) = 10;

ln(1024)/ln(2)=10;

2^10 = 1024;

In general the two based logarithm of x equals ln(x)/ln(2)

Even more general the N based logarithm of x equals ln(x)/ln(N)

:smileysurprised::):smileyvery-happy:

Link to post
Share on other sites

Miranda,

I see where you are going with this now. It is an interesting solution that I'd have to thing about how it could be structured in the current design architecture ...  As I think about it, the solution does seem possible without breaking the design ... basically would need to follow:

  1. HUD sends 1/2 the list in a message to a specific Prim using llRegionSayTo
  2. HUD then Loads the Script to said Prim
  3. Prim then splits the list and sends 1/2 (1/4) to another Prim ...
  4. etc

Could be an elegant solution and require less coding that having to deal with multiple delivery scripts etc ...

Looks like it should be straight forward ... back to coding :-)

 

Wanda

Link to post
Share on other sites

 

So .. I have been working on the path of having the Building Prims share the load of passing the scripts and have written the code for the HUD .. now off to the Building Prim Control code. I wanted to share the results with you all for any comments ... I should explain a few things beforehand:

You will see that the code does not actually make any outside calls. This is because of the way the solution is architected. I have a central HUD Control script, basically a crude message broker. That script takes care of all communications in and out of the HUD.

You may also notice that my header definition for the link_message() event handler is slightly different from the standard. This is to indicate what I am actually using the various calling parameters for. So:

link_message(integer sender_number, integer number, string message, key id) .. is changed to:

link_message(integer sender_number, integer channel, string action, key param)

  • I use the channel variable to filter internal messages to specific 'channels' of communication
  • I use the action variable to identify what action is being or has been called, i.e. what public function of the code module
  • and lastly in the param variable I pass the parameters needed. Thes are normally defined as value1|value2|...  , where value can be a further separated value as value1.1^value1.2^...

I have not included module level definitions of variables but my general convention is:

  • ALL_CAPS - A module level constant not changed by code in general
  • gVariable - a module level variable
  • variable - a local variable, if it is more than one word I will capitalize the first letter of succeeding words
  • function_name - all functions/subroutines are in lowercase with the words separated by an underscore

You will also see in here references to Bootstrap. As I mentioned, the Building Prims will contain a control script that manages the various worker scripts and is the script that communicates with the HUD. There will be situations though where this script as well will need to be updated and so the Bootstrap. It needs to be pushed out first, will remove the local control script and then call back advising that it is ready, which added a bit more complication to the work.

I have placed the relevant functions called, after the state code for ease of reading, normally these will appear at the very begining of the script after constant and variable definition.

Finally to set the stage: At this point we have selected the scripts we are going to send (gSelScr) and called out to all the prims gathering their Keys (gPrimKeys) ... and we are off:

 

state do_delivery{	state_entry()	{		//Advise begining delivery of scripts and that it could take some time		llOwnerSay("Begining to deliver scripts to prims, this could take a few minutes");				//Start the process .. if only one we are outta here .. otherwise will get a call-back		if (send_script_list())		{			state running;		}	}	link_message(integer sender_number, integer channel, string action, key param)	{		if (channel == CTRL_CHANNEL)		{			//Target List sent to a prim			if (action == TARGET_LIST_RCVD)			{				llSetTimerEvent(0.0);								//Load the scripts to the Prim				load_scripts(gCurChild, gSelScr);				//Next ones if the last then we are done				if (send_script_list())				{					state running;				}			}			//A Bootstrap script was loaded to the prim			else if (action == BOOTSTRAP_READY)			{				llSetTimerEvent(0.0);				//If we are at the end just send it the scripts				if (llGetListLength(gPrimKeys) == 0)				{					//Send the Scripts to Bootstrap					load_scripts(gCurChild, gSelScr);					//Done					state running;				}				//Other wise we send the list and wait for return				else				{					//Split & Send the list					//wait for Confirmation					split_send_list(gCurChild);				}			}		}	}	timer()	{		//TO BE COMPLETED: How to handle timeouts 	}	state_exit()	{		llOwnerSay("Scripts Delivered");	}}//Functions used in Script delivery to Building Primsinteger send_script_list(){	integer done = FALSE;	integer length = llGetListLength(gPrimKeys);		//Get the next Prim 	gCurChild = llList2String(gPrimKeys, 0);	//If we are at the end just send	if (length = 1)	{		//Clear the Prim list .. all done		gPrimKeys = [];				list sendList = gSelScr;				//If in BootStrap we send the BootStrap Script		if (gAction == BOOTSTRAP)		{			sendList = [bOOTSTRAP_CTRL];		}					//Send the Scripts		load_scripts(gCurChild, sendList);		//If in BootStrap we wait for it to answer		if (gAction == BOOTSTRAP)		{			llSetTimerEvent(10.0);		}		else		{			//Done			done = TRUE;		}	}	//Other wise we send the list and wait for return	else	{		//Remove the child from the list		gPrimKeys = llList2List(gPrimKeys, 1, length - 1);		//Split & Send the list waiting for Confirmation		split_send_list(gCurChild);	}	return done;	}split_send_list(string target){	//Split the remaining list in half	integer length = llGetListLength(gPrimKeys);	integer half = llFloor(length/2);	string passList = llDumpList2String(llList2List(gPrimKeys, half, length - 1), SEP);		gPrimKeys = llList2List(gPrimKeys, 0, half - 1);		//Send 1/2 the list to the prim	llMessageLinked(LINK_ROOT, CTRL_CHANNEL, TARGET_LIST, target + KP_SEP + passList);	//Will need acknowledgement prior to sending	llSetTimerEvent(10.0);}load_scripts(string target, list scripts){	integer scriptNum = llGetListLength(scripts);	integer x;	for (x = 0; x <= scriptNum; x++)	{		string name = llList2String(scripts, x);		llRemoteLoadScriptPin((key)target, name, LOAD_PIN, (name == BOOTSTRAP_CTRL), scriptNum);	}}//End Functions

 

Link to post
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...