These forums are CLOSED. Please visit the new forums HERE
What makes a laggy script? |
|
|
Ylikone Obscure
Amatuer Troll
Join date: 24 Jan 2007
Posts: 335
|
02-24-2007 13:27
Could people please list some of the main things that will cause a script to be laggy? I am slowly learning LSL and want to put good practices to use... but I can't really find any suggestions for methods to use or avoid when considering lag.
|
|
Frank Elderslie
Registered User
Join date: 26 Oct 2006
Posts: 8
|
02-24-2007 15:01
I'm novice myself, but I would advise you to keep your lists to a minimum. They eat up a lot of memory as I understand it, and I know from personal experience that this seems true.
-Frank |
|
Osgeld Barmy
Registered User
Join date: 22 Mar 2005
Posts: 3,336
|
02-24-2007 17:45
anything and everything you do in a script eats some cpu time but heres a few of the big killers
Fast Timers Timers with a high speed resolution are a big eater of cycles, ok maby when your running a gameshow you need that 1 second timer to let everyone know how much time they have left, but do you need that timer running an event to update your wall clock every second, in your house, that noone is in 22 hours a day? Fast Repeating Sensors Basicly the same as timers Open Listeners The llListen Function and event are one of the major workings of many many things in SL, if you set one up to listen to everybody / everything on channel 0 (which is open chat) it will listen to everyone and everything, this can get extreamly nasty in an enviroment thats really busy, the llListen function has filters for chat channel (/227) av name, uuid and a message make use of them whenever you can to narrow down the scope Prim Updates Changing color shape or anyother attrubute of a prim basicly causes the sim to recalc every peramater about that prim and resends it to every client in the area, like timers and sensors, when used in excess its a real load on the server IF trees OMG dont get me started, lets say you need alot of if's to complete a menu system dont just use if if if if if in your script, if condition 1 is met, it will still test for all the other conditions, which can be a debuging nightmare but also you really dont need to test 20 other conditions after the fact, its just a total waste of cpu cycles use else if, ie CODE
if x does infact == 0 it wont test to see if x == 1 ect but this will keep checking down the list untill TRUE as been returned soooo even faster ... binary CODE
Mathmatics If you can precalulate an awnser to a mathmatic question do it, wasting cpu cycles on math that never changes is just silly, course you cant always do that, part of scripting is dealing with dynamic data but keep it in mind example, a teleporter just for you, you could llGetPos, have it return 100 and have the script take 100 and add 250 to it, but if the darn thing isnt gonna move why waste the cycles each time you use it when we all know its just gonna end up as 350 anyways Lists As mentiond before lists are piggy, usefull since theres no arrays in LSL but piggy none the less, @ small sizes they arnt too terrible, but each element you put in a list uses that much memory + 40 bytes so they consume your script memory faily quickly, also at large sizes they take for ever to deal with, even with simple lookups... im not shure how bad they are on the simulator (im shure they suck tho) but they can drag your script to a screeching halt when dealing with large amounts of data, im not saying dont use them but alot of the time you can use a string as the same thing, which doesnt waste memory and doesnt suffer nearly as much in the speed department ok im shure i missed abunch but theres a decent list to start with, happy scripting and welcome to LSL ![]() |
|
Ylikone Obscure
Amatuer Troll
Join date: 24 Jan 2007
Posts: 335
|
02-24-2007 19:27
Thanks for the tips! Good information.
I was also wondering about the functions that make calls to the outside world like llHTTPRequest? What happens if the site your command is requesting is down or is slow, how do the command handle that? Can somebody bring down an entire sim by making a script that continually polls a website? |
|
Osgeld Barmy
Registered User
Join date: 22 Mar 2005
Posts: 3,336
|
02-24-2007 23:24
I was also wondering about the functions that make calls to the outside world like llHTTPRequest? What happens if the site your command is requesting is down or is slow, how do the command handle that? ive not seriously probed this, i use my own server for most of my meddling from what ive seen theres not a timeout, you request data and whenever it comes it the http event is fired when that event comes in the only thing you get is a string of text so you will have to deal with error messages and whatnot yourself, including making a timeout widget so your script doesnt sit in limbo forever if a site is down as far as XML-RPC i dont know ive not messed with that, i should but i havent Can somebody bring down an entire sim by making a script that continually polls a website? no there is a biult in throttle, they change it once in a while to "tune" it in since html access is a fairly recent addition, last one i remember was 20 requests per AGENT (as in the objects owner not per script) per 100 seconds altho i think they uped it since then, its still pretty locked down Thanks for the tips! Good information. |
|
Tyken Hightower
Automagical
Join date: 15 Feb 2006
Posts: 472
|
02-25-2007 00:33
Bad functions don't make scripts lag, bad algorithms do. Although, llFrand is one dirty little tool. No good ever comes of it in large amounts.
_____________________
![]() |
|
Nexus Laguna
Registered User
Join date: 20 Dec 2006
Posts: 40
|
02-26-2007 08:15
One function I have found that can cause signinficant lag is llInstantMessage. Most of the time there is a valid alternative such as llOwnerSay or even llWhisper ... I have been working on a script that HAS to use llInstantMessage and the lag on it can be quite large at times ... I have yet to find something to replace it that does not lag as much.
Something else to look out for as well are your global variables, ie. variables you declare outside of all functions and states and can be read in any state or function. The more global variables you have the higher your memory usage is as well and the more you will lag or slow down your script. The best way to use variables is to keep them as local as possible. For example, do you really need to keep track of clicks in one state using a global variable .. wouldn't a variable in your state work fine? If you can keep lists local to a state ... WOW .. one of the biggest memory savers that is. Timers, Listeners, and any other repeating events kept to a minimum is another good idea. Try to call a llListen only when you are expecting something to be said and use the handle to destroy a Listen when your done listening and a timer that runs once to timeout listening. Something like this... touch_start(integer num_clicks) { integer = listen_handle; llListen (0, llDetectedKey(0), "", 0); llSay(0, "Listening for 10 seconds" ;llSetTimerEvent(10); } timer () { llSay(0, "Heard Nothing. Stopping listening" ;llListenRemove (listen_handle); } listen (integer channel, string name, key id, string message) { llSay(0, "You were heard" ;llListenRemove(listen_handle); } Hope that helps lol. ![]() |
|
Baron Hauptmann
Just Designs / Scripter
Join date: 29 Oct 2005
Posts: 358
|
02-26-2007 09:01
Perhaps someone can clear up some confusion in my poor muddled brain.
I have understood that there are two types of variables: Global variables are declared outside of any state and persist across all states. Local variables are declared within (for lack of better terms) a set of curly braces. My question: Does a local variable declared within one event in a state persist across other events in that state? I had assumed from what I read that it is not the case. A quick test of Nexus's script in lslint says (among other errors) that "listen_handle is undeclared" in the timer event and listen event, which would seem to corroborate my understanding. Baron Hauptmann |
|
Tyken Hightower
Automagical
Join date: 15 Feb 2006
Posts: 472
|
02-26-2007 10:16
Perhaps someone can clear up some confusion in my poor muddled brain. I have understood that there are two types of variables: Global variables are declared outside of any state and persist across all states. Local variables are declared within (for lack of better terms) a set of curly braces. My question: Does a local variable declared within one event in a state persist across other events in that state? I had assumed from what I read that it is not the case. A quick test of Nexus's script in lslint says (among other errors) that "listen_handle is undeclared" in the timer event and listen event, which would seem to corroborate my understanding. Baron Hauptmann A variable in any event doesn't carry over to another state's event handler of the same type. Local variables only exist while that specific function/event/scope is being run. Also, global variables may add more memory usage, but they certainly won't 'lag' your scripts. If anything, using more local variables will cause lag as there are more operations being done, if I'm not mistaken (declaration and assignment as opposed to one initial declaration and only assignment down the road). Also, I'm wondering if Nexus' problems with llInstantMessage aren't due to the fact that it causes 2.0 seconds of delay after it's called.. It's designed to do that. _____________________
![]() |
|
Masakazu Kojima
ケロ
Join date: 23 Apr 2004
Posts: 232
|
02-26-2007 10:52
I was also wondering about the functions that make calls to the outside world like llHTTPRequest? What happens if the site your command is requesting is down or is slow, how do the command handle that? Can somebody bring down an entire sim by making a script that continually polls a website? |
|
Nexus Laguna
Registered User
Join date: 20 Dec 2006
Posts: 40
|
02-27-2007 04:01
A variable in any event doesn't carry over to another state's event handler of the same type. Local variables only exist while that specific function/event/scope is being run. Also, global variables may add more memory usage, but they certainly won't 'lag' your scripts. If anything, using more local variables will cause lag as there are more operations being done, if I'm not mistaken (declaration and assignment as opposed to one initial declaration and only assignment down the road). Also, I'm wondering if Nexus' problems with llInstantMessage aren't due to the fact that it causes 2.0 seconds of delay after it's called.. It's designed to do that. Yes my mistake sorry. The listen_handle variable had to be global as they do not persist over events in the same state. Apologies for that .. silly mistake on my part. Also, global variables are more time consuming as the variables have to be sustained whereas clearing variables from memory by keeping them local helps preserve that. llInstantMessage is not necessarily delayed by 2.0 seconds as I have used llInstantMessage and it is immediatly instant and other operations in the script run perfectly with no delay after calling llInstantMessage. I do sometimes get lag up to 5 seconds using llInstantMessage as well. The only reason I can think that llInstantMessage can lag badly is simply because of all the lookup it needs to do, i.e. lookup for avatar details, etc to get the message to its destination .. but this is purely a guess on my part. |
|
Learjeff Innis
musician & coder
Join date: 27 Nov 2006
Posts: 817
|
02-27-2007 07:02
We need to distinguish between two kinds of lag here.
First is the kind that slows down the sim in general: these laggy scripts hog the sim CPU and slow things down for everyone. Osgeld's excellent list is a good guideline for these. Second is the kind that causes lag for YOUR script, but doesn't bog the server unnecessarily. These are simply processing delays -- mostly, ones that were inserted there intentionally because overuse of these things WOULD bog the server if overused. llInstantMessage() is more of this kind than the sim laggers, unless you're doing large numbers of them for some reason. The first is hard to measure, unless you own an island and know how to do meaningful performance measurements. However, experienced programmers can make pretty good guesses and come up with lists like Osgeld's. The second is pretty easy to asses just by watching your script run. It's also important, but more from the perspective of the usability of your script. For this thread, I'd rather focus on the more important first aspect: bogging the server. Tyken's point is also a VERY important one to consider. It's easy to write a script that doesn't violate any of Osgeld's rules, but lags the heck out of the server. For example, any script that has a long loop, or that handles too many of any kind of event. The first key to coding for low lag is knowing how to count how many times something gets executed. This means knowing exactly what causes your event handlers to run, and then knowing how many times you'll go through any loops you might have. This is why open listens are bad ("open listens" being those where the channel is zero, the name is "", and the id is NULL_KEY), because your listen event gets executed for everything that anyone in hearing range says! Now imagine that script running in 20 poseballs in the room. So, the first cut for 'low-lag' coding is to make sure that your script rarely interacts, and only does so when someone specifically interacts with the object (e.g., touches it or sits on it). The second cut is understanding how many instances of your script might be present, and the environment in which it runs. If it's the kind of thing that a household or business is very unlikely to have more than one of, you have more leeway than if it's something like a script in a window where you could have dozens of them in one house, and hundreds in a sim. Finally: don't avoid lists! Often using a list is more efficient than trying to work around it. For example, if all you need to know is whether the user who clicked is 'authorized' based on card-configured names, it's far better to put all the names and use llListFindList() than to use a loop and compare against a number of variables or explicit compares to list elements. Just be aware that lists have a cost, and if there is a more elegant way to code that doesn't involve remembering lots of stuff, then it's probably a good idea. So, yes, lists are expensive. But when what you need to do involves tracking a number of related data items, lists are probably the best way -- don't try to find a better one. Try to find a way of NOT having to tracka number of related data items, and if you can, great. For example, using llSameGroup() rather than comparing the toucher against a configures set of users. PS: This topic should be a sticky! |
|
Learjeff Innis
musician & coder
Join date: 27 Nov 2006
Posts: 817
|
02-27-2007 07:09
Baron, good question but please start a new thread for it, it is unrelated to this one. If this thread goes sticky, it would be best for the moderator to delete your posts and the replies. (Along with this post!)
|
|
Learjeff Innis
musician & coder
Join date: 27 Nov 2006
Posts: 817
|
02-27-2007 07:24
Concerning local variables versus globals and their effect on lag:
In general, you should make a variable local or global based on your intent for the variable and its meaning (it's true scope), and not worry about lag. However, here are some points to keep in mind in cases where you could implement something different ways, one with more globals and one with more locals. Global variables take 'permanent' server resources (memory), and add more to save whenever the server saves the state of the object. (By 'permanent', I mean they exist as long as the script is in running state.) Allocation of locals takes a little time. In compiled, non-object-oriented languages like C, this is simply adding a value to the stack pointer, which happens anyway, and doesn't really add time. In interpreted languages like LSL, it's more complicated. Initialization of locals to non-default values also takes a little time in addition to the allocation time. This is especially true for lists, and to some extent, vectors and rotations. Therefore, if you have something you'd normally use as a local variable whose value never changes (i.e., a "manifest constant" as it's called in the programming business), it's probably better to use a global. I have no idea where the tradeoff is between the overhead for saving and restoring state of globals, versus allocating and freeing locals. I think it's best in general to simply follow good design practices and let the variables fall where they may. Oh, beware passing lists as function arguments in any context where it happens frequently. Don't worry about this for a function that only happens "per-touch", for example, i.e., rarely. But DO worry about it in tight loops that execute a large number of times, or in open listens. The reason to worry about this is because, IIRC, passing a list to a function causes the list to be copied. Again, though, only worry about this in special cases, when optimizing code that really shouldn't exist at all (that is, code that runs a lot) but is unavoidable for some reason. |
|
Baron Hauptmann
Just Designs / Scripter
Join date: 29 Oct 2005
Posts: 358
|
02-27-2007 08:37
Learjeff, the reason for my post was to establish whether or not Nexus' means of addressing lag was correct. I was pretty sure of the answer, but am not a programmer by profession, so did not want to state as a fact something that I had misunderstood.
Regarding lag and listens, I have another question that can perhaps be addressed more definitively here by those whose understanding far outstrips mine. I have heard numerous times DON'T LISTEN ON CHANNEL ZERO IF IT CAN BE HELPED or some derivative of that statement. If I use a filter to listen only for the owner of an object on channel 0, is that much worse than listening on a different channel? Oh, one other question about lag . . . I realize that there are certain functions that change attributes of a prim, like llSetTextureAnim and llParticleSystem. What effect is there on sim lag if I have a script call one of these and then go dormant (using llSetScriptState)? As I understand it, the script would no longer take resources, but what kind of drain is left by the texture anim and particle system? (especially if there are a BUNCH of these in one area???) (And thanks to those whose wisdom is slowly sinking into this thick skull!) Baron |
|
Jeff Kelley
Registered User
Join date: 8 Nov 2006
Posts: 223
|
02-27-2007 09:27
So, the first cut for 'low-lag' coding is to make sure that your script rarely interacts, and only does so when someone specifically interacts with the object (e.g., touches it or sits on it). Also, answer the question "when my script should run". Should it really run when I am offline? Should it run when there is no people around? There is no need to play the spinning-rotating-color-changing light-show 24/24, 7/7 if there is no one around. If it is for private use, consider shutting it of when you are offline. Have your windows and home appliances stop listening when you are offline. Set the default state to be a sleeping state and test evevy 2 or 3 minutes for online status or the presence of avatars. Then switch to a more responsive running mode. I find often desirable to have the default state inactive with no listener and no fast timer. States are good for that. Listeners are automatically flushed when you leave a state. A master script can set secondary scripts to sleep and wake them when necessary. Please, do NOT llSense every second. Except if you want an object "look at" an av, but again this can be limited to an interactive state, and the sense period lowered when the av leaves the active range. Think that objects with different states with different behaviours may look more intelligent than objects doing over and over and over the same thing. Reducing lag is of premium importance as we see more and more sims hogged by awful script time (i have surges to 150mS in Bassenthwaite) with according time dilations. It is our responsability, as scripters, not to give or sell laggy scripts which will be cloned thousands of times. |
|
Lash Stringfellow
Registered User
Join date: 17 Dec 2006
Posts: 3
|
Color texture change lag for HUD?
02-27-2007 09:34
I have a question related to the lag induced by changing colors and textures on a prim.
I understand that changing these properties on a prim in world requires the server to send updates to all agents in the viewing range, but what if it is a HUD? Does it only update the client? The reason I ask is that I have a single prim HUD that indicates its status and modes by changing colors and textures on various sides and by setting the prim's text. I love the feed back it gives, but I don't want to cause undue lag. Also, I assume that setting text falls under this category too, right? Seems as if it should. Thanks all, -Lash |
|
Masakazu Kojima
ケロ
Join date: 23 Apr 2004
Posts: 232
|
02-27-2007 13:48
Also, global variables are more time consuming as the variables have to be sustained whereas clearing variables from memory by keeping them local helps preserve that. llInstantMessage is not necessarily delayed by 2.0 seconds We need to distinguish between two kinds of lag here. As an experiment, pull up the stats window (ctrl-shift-1) and expand the simulator box and the time (ms) box under that. Make a script like "integer i; while (1) ++i;" or anything you think would be laggy. Keep an eye on the the "Script Perf", "Script Time" and "Total Frame Time" fields. Even if you make a lot of copies (try 50-150), the script time and total frame time should remain stable. Script Perf (instructions per second) might go up or down depending on what you do. The example above should make it increase dramatically. A rapid sensor with no actual event handler should make it decrease, presumably because script time is being spent on the sensors instead of executing instructions. If someone's experience with this differs it would be interesting to hear about. Global variables take 'permanent' server resources (memory), and add more to save whenever the server saves the state of the object. (By 'permanent', I mean they exist as long as the script is in running state.) Initialization of locals to non-default values also takes a little time in addition to the allocation time. PS: This topic should be a sticky! |