LSL functions you should NEVER call

Creating scripts
User avatar
Kayaker Magic
Posts: 338
Joined: Sun Dec 01, 2013 8:40 am
Has thanked: 48 times
Been thanked: 354 times

LSL functions you should NEVER call

Post by Kayaker Magic » Wed Jan 15, 2014 11:01 pm

As you know, many of the functions in the LSL library (llSetPos, llSetRot, llSetPrimitiveParameters, etc) have a built-in delay.
It turns out that this delay is implemented in a VERY BAD WAY in Open Simulator, and it can seriously mess up your SIM. I'm including an article below that I wrote for the OSGrid forum explaining why. The thing that you can do about this is never call one of these routines unless you have no choice. Unfortunately many free scripts that people have used for years in SL can cause big problems in Open Sim based grids. For example, I saw a SIM that had 300 blinking lights at Xmas time. Each light called llSetPrimitiveParams to turn glow on and off. The lights kept blinking, but no other scripts in the SIM could run at all! We replaced all of these scripts with one that called llSeLinktPrimitiveParamsFast, and the SIM worked fine.

Here's a (probably incomplete) list of routines you should never call, and how to do the same thing without locking up a SIM:

llSleep(); Avoid this whenever possible. Use timers, re-write your code to be event driven.
llSetPos(pos); replace with llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POSITION,pos]);
llSetRot(rot); replace with llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROTAZTION,rot]);
llSetPrimitiveParams([]); replace with llSetLinkPrimitiveParamsFast(LINK_THIS,[]);
llSetLinkPrimitiveParams(link,[]); replace with llSetLinkPrimitiveParamsFast(link,[]);

Technical Explanation:

XEngine, the part of Open Sim that runs scripts, can only run a handful of scripts at once. Each running script is processed in a separate thread. A thread is like a separate processor. (And if you are lucky your server has multiple processor cores and each script does run in another core.) When a script is waiting for an event, like a timer or a touch, it does not need the thread and that thread can be re-used for a different script. When an event happens, a thread is assigned to a script and it is allowed to run again. So if all your scripts are basically event driven, you can have 1000's of them all waiting for events without using a lot of SIM resources.

Because there are a limited number of threads in a SIM, if an event needs to happen and all the threads are already working on other scripts, the new event will have to wait for some other script to release a thread first. This could cause lag if the wait becomes very long. On the other hand, if all your scripts are well-behaved and return from events as soon as possible, this will not be a problem.

llSleep is a special problem. Instead of returning the thread for other scripts to use, it locks up the thread for the requested time. I assume this was done because events can only happen once a “heartbeat” which is 11 times a second or about once every 0.09 seconds. Locking the thread allows pausing the script for short accurate times, much shorter than the heartbeat. But if too many scripts all call llSleep at about the same time, all the threads can get locked up and NO OTHER SCRIPTS can run.

No problem you say, I'll never use llSleep again! It turns out that lots of LSL functions have a delay, and this delay is implemented by stopping the thread exactly the same way that llSleep works! If you call llSetPos, llSetRot, llSetPrimitiveParams, llSetLinkPrimitiveParams, llCreateLink, llDialog, llEmail (20 SECONDS!), llGiveInventory, llGiveInventoryList, llInstantMessage, llRezObject, llRezAtRoot, llSetLocalRot, ALL OF THESE FUNCTIONS INCUR AN LLSLEEP-LIKE DELAY WHEN YOU CALL THEM! (And a few more that I missed). Many of these functions can be done by calling llSetLinkPrimitiveParamsFast instead, so you should re-write your scripts to use this whenever possible. Note that although it is intended for moving child prims, if you call it from the root prim with LINK_THIS as the first argument, it moves the entire link set just like llSetPos. (Or rotates it, or whatever).

Timing things is a little more difficult. If you need a delay and don't care how long it is, you can use llSetTimerEvent. This has a limit in OS that it can never set a timer that is less than 0.5 seconds. Plus if you need to time several different things, your timer event can get complicated as it tries to figure out why you called. The advantage of timers is that when you start one (then exit your current event), the thread you are using is freed up for some other script to use in the mean time.
These users thanked the author Kayaker Magic for the post (total 8):
Ilan TochnerGraham Millsonyxty deltaKeith SelmesHandy LowJack SpadeEldovar LamiltonShandon Loring
User avatar
Dundridge Dreadlow
Posts: 616
Joined: Mon May 06, 2013 2:23 pm
Location: England
Has thanked: 590 times
Been thanked: 337 times

Re: LSL functions you should NEVER call

Post by Dundridge Dreadlow » Wed Jan 15, 2014 11:15 pm

I never liked most of those functions anyway :D
ImageImageImageImageImageImage
PS. Kitely is awesome.
onyxty delta
Posts: 40
Joined: Wed Jun 05, 2013 12:04 am
Has thanked: 25 times
Been thanked: 20 times

Re: LSL functions you should NEVER call

Post by onyxty delta » Thu Jan 16, 2014 2:57 am

I would argue they don't really work that well in SL either. I learned early on to use llSetLinkPrimitiveParamsFast do to timing issues. Very annoying. Thanks for the post!
User avatar
Handy Low
Posts: 231
Joined: Fri Nov 08, 2013 3:38 pm
Location: Yorkshire, England
Has thanked: 207 times
Been thanked: 140 times
Contact:

Re: LSL functions you should NEVER call

Post by Handy Low » Thu Jan 16, 2014 9:53 am

Thanks for the warning. What a crazy situation - I wonder if there's any chance of this being fixed.

I'm pretty sure I don't use any of those functions in my scripts (I'll check), but that's mostly luck - after all, functions like llEmail(), llGiveInventory() and llRezObject() are pretty much irreplaceable if the functionality of the script demands them.

It's issues like this that make people reluctant to take scripts from SL into OpenSim.
Handy Low
User avatar
Deuce Halsey
Posts: 322
Joined: Mon Oct 14, 2013 9:30 pm
Has thanked: 391 times
Been thanked: 260 times

Re: LSL functions you should NEVER call

Post by Deuce Halsey » Thu Jan 16, 2014 11:48 pm

The only one of the mentioned functions that I use is llGiveInventory(). I use this one for note card givers in my world. It's just a simple touch the object and get a notecard kind of deal. I can't imagine this causing any problems for me or my visitors - I certainly haven't noticed anything to date that would give me pause. I suppose it is something to keep in mind if I would be considering having a note card giver at a large event where tons of people might be requesting the information at the same time.

Thanks so much for this information - good stuff to keep in mind when scripting.
Deuce Halsey
Just4yucks in Kitely Marketplace
http://www.kitely.com/market?store=2704782
User avatar
Jack Spade
Posts: 20
Joined: Thu Sep 26, 2013 9:57 pm
Has thanked: 8 times
Been thanked: 8 times

Re: LSL functions you should NEVER call

Post by Jack Spade » Sat Jan 18, 2014 1:13 am

That's... really ugly. Thanks for letting us know this. Some of my stuff will not scale at all, given this; I'll go back and rework it, though the resulting code is going to look terrible. (Which of the 0.2 second delays was this timer for again?)
User avatar
Angel Feijoo
Posts: 10
Joined: Tue Aug 12, 2014 4:16 pm
Has thanked: 6 times
Been thanked: 2 times

Re: LSL functions you should NEVER call

Post by Angel Feijoo » Mon Jan 12, 2015 8:47 pm

Kayaker Magic wrote: XEngine, the part of Open Sim that runs scripts, can only run a handful of scripts at once. Each running script is processed in a separate thread. A thread is like a separate processor.
Thanks to Kayaker's post mentioning the script execution threads, I realized why my new thousand-scripted-prims project was not working.

Question 1: When the maximum number of threads (set by the MaxThreads parameter?) are being executed, what happens with the new event requests that are waiting? Can some of those events be just ignored/skipped by XEngine? Or can some waiting scripts even be halted? In my project, when I have many scripts trying to run, the latter ones just act randomly. I mean, not only some lag happens, but the scripts act erratically, and I don’t know how to keep that under control.

Question 2: Can I know what is the default MaxThreads value in Kitely? And, can I change it for one of my worlds?
User avatar
Ilan Tochner
Posts: 4868
Joined: Sun Dec 23, 2012 8:44 am
Has thanked: 2587 times
Been thanked: 2626 times
Contact:

Re: LSL functions you should NEVER call

Post by Ilan Tochner » Wed Jan 14, 2015 12:56 am

Hi Angel,

We prefer to keep with the default OpenSim configuration values whenever possible in order to avoid compatibility problems when people move content to or from Kitely.

The same MaxThreads setting is used for all Kitely worlds.
hanif noor 3
Posts: 1
Joined: Mon Mar 07, 2016 10:57 am
Has thanked: 0
Been thanked: 0

Re: LSL functions you should NEVER call

Post by hanif noor 3 » Mon Mar 07, 2016 10:57 am

Can some of those events be just ignored/skipped by XEngine? Or can some waiting scripts even be halted? In my project, when I have many scripts trying to run, the latter ones just act randomly.
NOOR
User avatar
Ilan Tochner
Posts: 4868
Joined: Sun Dec 23, 2012 8:44 am
Has thanked: 2587 times
Been thanked: 2626 times
Contact:

Re: LSL functions you should NEVER call

Post by Ilan Tochner » Mon Mar 07, 2016 11:09 am

Hi hanif,

Anything can be done if we spend the time to update XEngine but that isn't something we'd like to pursue given that OpenSim 0.9.0 has made changes to this module and we're sticking with OpenSim 0.8.2 until OpenSim 0.9.0 becomes stable enough to be officially released.
Post Reply