Script suggestion - SLUniverse Forums
Navigation » SLUniverse Forums > Development Discussion and Support > Scripting » Script suggestion


Scripting Discuss scripting and programming for SL and other platforms

 
Reply
 
LinkBack Thread Tools Display Modes
Old 03-17-2017, 09:34 AM   #1 (permalink)
Junior Member
 
Join Date: Mar 2017
Posts: 5
Script suggestion

Hello everyone, I'm rather new to LSL so I would humbly ask for some pointers...
Namely I am making a script that should pick up inventory names (notecards only) with specific names and later pack them into llDialog options...

Now, this is something I have whipped up, but not sure how fast/optimized it is. I mean it works, but I suspect that it can be more simpler if anything.

Code:
cache_inventory() {
    llSetText("Caching forms ...", <1,1,0>, 1);
    forms = [];
    forms_count = 0;
    integer i;
    forms_count = llGetInventoryNumber(INVENTORY_NOTECARD);
    
    for (i = 0; i < forms_count; i++) {
        string sep = "_";
        string invname = llGetInventoryName(INVENTORY_NOTECARD, i);
        list l = llParseString2List(invname,[sep], []);
        integer ll = llGetListLength(l);
        string formIdentifier = llList2String(l, 0);
        // case sensitive because we want it that way ;)
        if (formIdentifier == "Form") {   
            forms = (forms = []) + forms + invname;
        }
    }

    page_count = forms_count / 6;
    if (forms_count % 6 > 0)
        page_count++;

    llSetText("", ZERO_VECTOR, 0);
}
Any tips would be appreciated, thanks.

Edit: Let me be clear, I am not asking for someone to write me better script (although suggestions are more than welcomed), but to tell me what I am doing wrong (so that I never ask related question again )

Last edited by Buzdovan; 03-17-2017 at 09:41 AM. Reason: disclaimer
Buzdovan is offline   Reply With Quote
1 User Said Yay!:
Old 03-17-2017, 10:32 AM   #2 (permalink)
Particle Laboratory Elf
 
Jopsy Pendragon's Avatar
Dump the Trump
 
Join Date: Nov 2008
Location: San Diego
Posts: 10,497
My Mood:
SL Join Date: Jan 15 2004
Business: Light Sorcery

Awards: 1
SLU Creepy Avatar Competition 2014 Participant 
Perhaps something like:


If (llSubString(invname, 0, 5)=="Form ") { ....


Also,
forms = (forms = []) + forms + invname;
Seems painfully convoluted, why not simply:

forms += [invname];
Jopsy Pendragon is offline   Reply With Quote
1 User Said Thanks:
Old 03-17-2017, 10:57 AM   #3 (permalink)
Senior Member
 
Sei Lisa's Avatar
My first name is Sei
 
Join Date: Aug 2013
Posts: 172
My Mood:
Actually, it seems that the separator should be "_" rather than a space (and the last parameter is the last position, not the length), thus it would be like this:

PHP Code:
if (llGetSubString(invname04) == "Form_") ... 
And this is even simpler for adding to the list:
PHP Code:
forms += invname
The (list = []) + list trick is OK for LSO, but I don't recommend new scripts to be compiled with LSO. It typically takes more sim resources than the same script in Mono.

Edit: also, this part has two problems:
PHP Code:
list llParseString2List(invname,[sep], []);
integer ll llGetListLength(l);
string formIdentifier llList2String(l0); 
First, ll is not used anywhere else, so that line can be completely eliminated.

Second, llParseString2List would skip empty sections, therefore the filter would pass Form_xxx but also _Form_xxx or __Form_xxx.

That's moot if the method is changed to Jopsy's, of course.
__________________
Tools for scripters that I'm the maintainer of:
LSL-PyOptimizer (NEW: Try it online!) | LSL Calculator | Unofficial LSL Reference Wiki | LSL Keywords Database

Last edited by Sei Lisa; 03-17-2017 at 11:09 AM.
Sei Lisa is offline   Reply With Quote
2 Users Said Thanks :
Old 03-17-2017, 11:46 AM   #4 (permalink)
Particle Laboratory Elf
 
Jopsy Pendragon's Avatar
Dump the Trump
 
Join Date: Nov 2008
Location: San Diego
Posts: 10,497
My Mood:
SL Join Date: Jan 15 2004
Business: Light Sorcery

Awards: 1
SLU Creepy Avatar Competition 2014 Participant 
Also, strong style preference, I would -never- use lowercase L or uppercase i as variable names. Depending on the font, they can be too difficult to discern visually.

And thanks for catching that it was 0,4, not 0,5. =)

And... in the case that a notecard has a hard to see leading space (can't recall if that's possible or not) but it'd be safer to strip that out with:

if (llGetSubString( llStringTrim(invname,STRING_TRIM_HEAD) , 0, 4) == "Form_") ...
Jopsy Pendragon is offline   Reply With Quote
1 User Said Thanks:
1 User Agreed:
Old 03-17-2017, 11:48 AM   #5 (permalink)
Junior Member
 
Twisted Pharaoh's Avatar
Along with Athena, move also your hand
 
Join Date: Feb 2010
Posts: 2,137
My Mood:
SL Join Date: Yesterday
page_count = (forms_count+5) / 6;
__________________
Quote:
Originally Posted by Chuang Tzu
If he who bursts out in anger is not really angry, then his anger is an outburst of nonanger. If he who launches into action is not really acting, then his action is a launching into inaction. He who wishes to be still must calm his energies; he who wishes to be spiritual must compose his mind; he who in his actions wishes to hit the mark must go along with what he cannot help doing. Those things that you cannot help doing - they represent the Way of the sage.
Twisted Pharaoh is offline   Reply With Quote
1 User Said Thanks:
1 User Agreed:
Old 03-17-2017, 01:15 PM   #6 (permalink)
That Bitch

*SLU Supporter*
 
Void's Avatar
Innocent as far as you know
 
Join Date: Nov 2011
Location: Online
Posts: 14,580
My Mood:
SL Join Date: late 04 original account, mid 05 current
page_count = (integer)(forms_count + 5) / 6);

you should remove variable declaration to outside of the loop to save on instanciation cost. this would also let you inline several statements to save on reference count

the loop can be tightened up by grabbing the inventory count and walking it backwards (allowing you use a while loop),
PHP Code:
if (forms_count)
  while (
forms_count){
       
invname llGetInventoryNameINVENTORY_NOTECARD, --forms_count );
      
//-- other loop logic
  
}

that gives the list in reverse order unless you add to the front (but that would remove most of the benefit). unfortunately you can't do negative indexing because llGetIventory* doesn't understand them
__________________
- These eyes can do more than see
Quote:
Originally Posted by Cajsa Lilliehook View Post
It's not enough to care about liberty if the only liberty you care about is your own.
Quote:
Originally Posted by Jupiter Firelyte View Post
Why doesn't anyone ever ask, "What is the real meaning of the winter solstice?"
Quote:
Originally Posted by Eboni Khan View Post
Thanks for being passive agressive.
Void is offline   Reply With Quote
1 User Said Thanks:
Old 03-17-2017, 02:46 PM   #7 (permalink)
Junior Member
 
Join Date: Mar 2017
Posts: 5
Wow, first of all than you everyone for feedback, didn't expected that much comments, you gals and guys are awesome. Now

Quote:
Originally Posted by Jopsy Pendragon View Post
Perhaps something like:
If (llSubString(invname, 0, 5)=="Form ") { ....
Also,
forms = (forms = []) + forms + invname;
Seems painfully convoluted, why not simply:
forms += [invname];
The reason why I have opted for llParseString2List route is because I wanted (which I havent explained in origianl post) to do something like Form_<string>:<string> and later parse the rest of the strings in notecard name. But this is more clean anyway, and I can later on (since I am going to read contents of them as well, pass the full name to script via variable in notecard. I will pass the notecards anyway, so its simple to add variable to notecard and read it later on...

Quote:
Originally Posted by Sei Lisa View Post
The (list = []) + list trick is OK for LSO, but I don't recommend new scripts to be compiled with LSO. It typically takes more sim resources than the same script in Mono.
Yeah I have read it on Wiki I think about memory fragmentation... Speaking of which, is there any particular case where you would WANT LSO over Mono?

Quote:
Originally Posted by Sei Lisa View Post
Edit: also, this part has two problems:
PHP Code:
list llParseString2List(invname, [sep], []);
integer ll llGetListLength(l);
string formIdentifier llList2String(l0); 
First, ll is not used anywhere else, so that line can be completely eliminated.
Second, llParseString2List would skip empty sections, therefore the filter would pass Form_xxx but also _Form_xxx or __Form_xxx.
That's moot if the method is changed to Jopsy's, of course.
Yeah, went for Joopsy's solution altogether, and I wanted something with the llListLenght but cant recall what or why at the moment

Quote:
Originally Posted by Void View Post
page_count = (integer)(forms_count + 5) / 6);

you should remove variable declaration to outside of the loop to save on instanciation cost. this would also let you inline several statements to save on reference count

the loop can be tightened up by grabbing the inventory count and walking it backwards (allowing you use a while loop),
PHP Code:
if (forms_count)
  while (
forms_count){
       
invname llGetInventoryNameINVENTORY_NOTECARD, --forms_count );
      
//-- other loop logic
  
}

that gives the list in reverse order unless you add to the front (but that would remove most of the benefit). unfortunately you can't do negative indexing because llGetIventory* doesn't understand them
Thanks Twisted Pharaoh and Void Singer for explanation and the tips on saving reference count and reverse order trick.

Overall than you all again for the time to actually explain what, why and where. Cheers
Buzdovan is offline   Reply With Quote
Old 03-17-2017, 03:16 PM   #8 (permalink)
Senior Member
 
Join Date: Jul 2011
Location: UK
Posts: 4,163
Quote:
Originally Posted by Buzdovan View Post
[] Speaking of which, is there any particular case where you would WANT LSO over Mono? []
Back when Mono was new, transferring running Mono scripts from one simulator to another when crossing region boundaries or teleporting consumed a huge amount of sim resources, and had a very noticeable effect on sim frame rates, so it was generally seen as a common courtesy to use LSO compiled scripts for attachments. Also, an LSO script used 16k of memory while a Mono script used 64k, providing ammunition for a resurgent script Nazi movement.

I can't think of any advantages at all to using LSO instead of Mono nowadays.
KT Kingsley is offline   Reply With Quote
1 User Said Thanks:
Old 03-17-2017, 03:58 PM   #9 (permalink)
Junior Member
 
Join Date: Mar 2017
Posts: 5
So basically its safe to say Mono should be ticked by default. Thanks KT Kingsley
Buzdovan is offline   Reply With Quote
Old 03-17-2017, 05:29 PM   #10 (permalink)
Junior Member
 
Twisted Pharaoh's Avatar
Along with Athena, move also your hand
 
Join Date: Feb 2010
Posts: 2,137
My Mood:
SL Join Date: Yesterday
Quote:
Originally Posted by Void View Post
page_count = (integer)(forms_count + 5) / 6);
Ok for the cast, but there are 2 opening parenthesis and 3 closing in this line.

By the way, is the cast really necessary?

Last edited by Twisted Pharaoh; 03-17-2017 at 05:42 PM.
Twisted Pharaoh is offline   Reply With Quote
1 User Said Thanks:
Old 03-17-2017, 05:59 PM   #11 (permalink)
Particle Laboratory Elf
 
Jopsy Pendragon's Avatar
Dump the Trump
 
Join Date: Nov 2008
Location: San Diego
Posts: 10,497
My Mood:
SL Join Date: Jan 15 2004
Business: Light Sorcery

Awards: 1
SLU Creepy Avatar Competition 2014 Participant 
Quote:
Originally Posted by Buzdovan View Post
Yeah I have read it on Wiki I think about memory fragmentation...
Not really much of a concern in "DO THIS ONCE" kinds of code blocks.
Jopsy Pendragon is offline   Reply With Quote
1 User Said Thanks:
1 User Agreed:
Old 03-18-2017, 07:59 AM   #12 (permalink)
Senior Member
 
Sei Lisa's Avatar
My first name is Sei
 
Join Date: Aug 2013
Posts: 172
My Mood:
Quote:
Originally Posted by Void View Post
page_count = (integer)(forms_count + 5) / 6);
forms_count should be an integer. The division should therefore be integer division already.

Quote:
Originally Posted by Void View Post
you should remove variable declaration to outside of the loop to save on instanciation cost. this would also let you inline several statements to save on reference count
There's no instantiation cost in Mono. The only possible cost is an extra implicit assignment when declaring a variable without assigning it, that would be incurred when using your suggestion.

Quote:
Originally Posted by Void View Post
the loop can be tightened up by grabbing the inventory count and walking it backwards (allowing you use a while loop),
PHP Code:
if (forms_count)
  while (
forms_count){
       
invname llGetInventoryNameINVENTORY_NOTECARD, --forms_count );
      
//-- other loop logic
  
}

The 'if' is not necessary. The 'while' already takes care of the empty case.
Sei Lisa is offline   Reply With Quote
Old 03-18-2017, 08:00 AM   #13 (permalink)
That Bitch

*SLU Supporter*
 
Void's Avatar
Innocent as far as you know
 
Join Date: Nov 2011
Location: Online
Posts: 14,580
My Mood:
SL Join Date: late 04 original account, mid 05 current
Quote:
Originally Posted by Twisted Pharaoh View Post
Ok for the cast, but there are 2 opening parenthesis and 3 closing in this line.

By the way, is the cast really necessary?
good catch.

technically no, the backend should add the cast implicitly, but it's good practice to ensure it's there for other environments, and does not affect code size in LSL

@OP: re LSO vs Mono
the only advantage of LSO is competitive weapon and vehicle scripting for region crossing, simply because they are a little closer to continuous than MONO... and then only if they're streamlined to minimize instruction chains. for everything else MONO is far superior in general

Quote:
Originally Posted by Sei Lisa View Post
forms_count should be an integer. The division should therefore be integer division already.
AFAIK neither LSO nor mono differntiate division type, and insert an implicit cast

Quote:
There's no instantiation cost in Mono. The only possible cost is an extra implicit assignment when declaring a variable without assigning it, that would be incurred when using your suggestion.
I can't say for sure on mono because of the block memory useage (and I've never dug into the internals), but definitely in LSO and most other environments you run into it, and possible overloading as well

Quote:
The 'if' is not necessary. The 'while' already takes care of the empty case.
good catch, I'm so used to doing odd loops I just inserted the safety check without thinking = X

Last edited by Void; 03-18-2017 at 08:12 AM.
Void is offline   Reply With Quote
Old 03-18-2017, 08:21 AM   #14 (permalink)
Senior Member
 
Wanda Belinda's Avatar
 
Join Date: Oct 2016
Posts: 1,492
LSO supports a billion unicode characters where mono only supports a million which I'm sure is of great concern to many coders out there.
Wanda Belinda is offline   Reply With Quote
1 User Laughed:
Old 03-18-2017, 01:10 PM   #15 (permalink)
Senior Member
 
Sei Lisa's Avatar
My first name is Sei
 
Join Date: Aug 2013
Posts: 172
My Mood:
Quote:
Originally Posted by Void View Post
AFAIK neither LSO nor mono differntiate division type, and insert an implicit cast
Both do differentiate, and none does insert a cast when both operands are integers. It follows C semantics. See below. In LSO, there are explicit opcodes for every combination of integer and float; in Mono, an implicit cast is inserted if one of the elements is integer and the other is a float, but if both are integer, then integer division is performed instead.

Quote:
Originally Posted by Void View Post
I can't say for sure on mono because of the block memory useage (and I've never dug into the internals), but definitely in LSO and most other environments you run into it, and possible overloading as well
No, not even in LSO. I know it because I've dug into the internals (it was an essential step for writing my optimizer).

To illustrate it, I've created two example scripts, that only differ in whether the list declaration is inside or outside the loop:

PHP Code:
default
{
    
state_entry()
    {
        
2;
        
1.0 2;
        
2.0;
        
integer i;
        while (++
10)
        {
            list 
llParseString2List("x", ["y"], []);
        }
    }

PHP Code:
default
{
    
state_entry()
    {
        
2;
        
1.0 2;
        
2.0;
        
integer i;
        list 
a;
        while (++
10)
        {
            
llParseString2List("x", ["y"], []);
        }
    }

and run the LSO and Mono compiler on both, with assembler output.

To make it short, here's the diff:

Code:
$ diff -u scripts/declare-{in,out}side-loop.cil
--- scripts/declare-inside-loop.cil    2017-03-18 18:12:41.000000000 +0100
+++ scripts/declare-outside-loop.cil    2017-03-18 18:20:43.000000000 +0100
@@ -32,6 +32,8 @@
 pop
 ldc.i4.0
 stloc.s 0
+call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::CreateList()
+stloc.s 1
 LabelTempJump2:
 ldc.i4 10
 ldloc.s 0
@@ -47,7 +49,9 @@
 call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::Prepend(object, class [mscorlib]System.Collections.ArrayList)
 call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::CreateList()
 call class [mscorlib]System.Collections.ArrayList class [LslLibrary]LindenLab.SecondLife.Library::'llParseString2List'(string, class [mscorlib]System.Collections.ArrayList, class [mscorlib]System.Collections.ArrayList)
+dup
 stloc.s 1
+pop
 br LabelTempJump2
 LabelTempJump3:
 ret
And for LSO:
Code:
$ diff -u scripts/declare-{in,out}side-loop.out
--- scripts/declare-inside-loop.out    2017-03-18 18:12:41.000000000 +0100
+++ scripts/declare-outside-loop.out    2017-03-18 18:20:43.000000000 +0100
@@ -39,7 +39,8 @@
 POPBP
 CALLLID llParseString2List, 214
 POPBP
-STORELP 4 [a]
+STOREL 4 [a]
+POPL
 JUMP ##Temp Jump 0##
 LABEL ##Temp Jump 1##
 POPL
The diffs show that the declaration outside the loop consumes more memory in both Mono and LSO (in Mono, there are only extra instructions, and in LSO, there is a replaced instruction and a new one).

As for the division, note that even Python up to version 2 works like that. Here's the full generated CIL code for the first script, with comments I've inserted, which shows that the division is integer division when both dividend and divisor are integers, and float otherwise (warning: wall of text):

Code:
; boilerplate stuff
.assembly extern mscorlib {.ver 1:0:5000:0}
.assembly extern LslLibrary {.ver 0:1:0:0}
.assembly extern LslUserScript {.ver 0:1:0:0}
.assembly extern ScriptTypes {.ver 0:1:0:0}
.assembly 'LSL_00000000_0000_0000_0000_000000000000' {.ver 0:0:0:0}
.class public auto ansi serializable beforefieldinit LSL_00000000_0000_0000_0000_000000000000 extends [LslUserScript]LindenLab.SecondLife.LslUserScript
{

; constructor (initializes globals; since there are none, it's empty)
.method public hidebysig  specialname  rtspecialname instance default void .ctor ()  cil managed
{
.maxstack 500
ldarg.0
call instance void [LslUserScript]LindenLab.SecondLife.LslUserScript::.ctor()
ret
}

; state_entry()
; {
.method public hidebysig instance default void edefaultstate_entry() cil managed
{
.maxstack 500
.locals init (int32, class [mscorlib]System.Collections.ArrayList)

; 1 / 2;
ldc.i4 2  ; stack: 2
ldc.i4 1  ; stack: 2, 1
call int32 [LslUserScript]LindenLab.SecondLife.LslUserScript::Divide(int32, int32)
          ; stack: 0 (integer division of 1/2)
pop       ; stack: (empty)

; 1.0 / 2;
ldc.i4 2  ; stack: 2
conv.r8 ; implicit typecast to float
          ; stack: 2.0
ldc.r8 (00 00 00 00 00 00 f0 3f)
          ; stack: 2.0, 1.0
call float64 [LslUserScript]LindenLab.SecondLife.LslUserScript::Divide(float64, float64)
          ; stack: 0.5
pop       ; stack: (empty)

; 1 / 2.0;
ldc.r8 (00 00 00 00 00 00 00 40)
          ; stack: 2.0
ldc.i4 1  ; stack: 2.0, 1
conv.r8 ; implicit typecast to float
          ; stack: 2.0, 1.0
call float64 [LslUserScript]LindenLab.SecondLife.LslUserScript::Divide(float64, float64)
          ; stack: 0.5
pop       ; stack: (empty)

; integer i;
ldc.i4.0   ; load integer 0
stloc.s 0  ; store it into first local (i has index 0)
; while (++i < 10)
; {
LabelTempJump2:
ldc.i4 10  ; load integer 10              ; stack: 10
ldloc.s 0  ; load value of i              ; stack: 10, i
ldc.i4.1   ; load integer 1               ; stack: 10, i, 1
add        ; i + 1                        ; stack: 10, i+1
dup        ; duplicate i + 1 on the stack ; stack: 10, i+1, i+1
stloc.s 0  ; store i + 1 in i             ; stack: 10, i+1 (before the increment)
cgt        ; 10 > i+1?                    ; stack: (comparison result, 0 or 1)
brfalse LabelTempJump3 ; jump if 10 was NOT > i+1; stack: (empty)
; list a = llParseString2List("x", ["y"], []);
ldstr "x"  ; stack: "x"
ldstr "y"  ; stack: "x", "y"
call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::CreateList()
           ; stack: "x", "y", []
call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::Prepend(object, class [mscorlib]System.Collections.ArrayList)
           ; stack: "x", ["y"]
call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::CreateList()
           ; stack: "x", ["y"], []
call class [mscorlib]System.Collections.ArrayList class [LslLibrary]LindenLab.SecondLife.Library::'llParseString2List'(string, class [mscorlib]System.Collections.ArrayList, class [mscorlib]System.Collections.ArrayList)
           ; stack: ["x"] (result of llParseString2List)
stloc.s 1  ; store the result in a, which has index 1; stack: (empty)
; } // close loop
br LabelTempJump2 ; loop
LabelTempJump3: ; jump here when the loop finishes
; } // close event
ret
}

}
And the corresponding assembly in LSO (without comments inserted this time, as I don't understand some opcodes):
Code:
Function Args: 
Local List: il
STATES
default:
EVENTS
state_entry()
PUSHARGI 2
PUSHARGI 1
DIV integer, integer
POP
PUSHARGI 2
PUSHARGF 1.00000
DIV integer, float
POP
PUSHARGF 2.00000
PUSHARGI 1
DIV float, integer
POP
LABEL ##Temp Jump 0##
PUSHARGI 10
PUSHARGI 1
PUSH 0 [i]

ADD integer, integer
STORE 0 [i]
LESS integer, integer
JUMPNIF ##Temp Jump 1##
PUSHE
PUSHE
PUSHBP
PUSHARGS "x"
PUSHARGS "y"
PUSHARGB 3
STACKTOL 1
PUSHARGE 0
PUSHSP
PUSHARGI 12
ADD integer, integer
POPBP
CALLLID llParseString2List, 214
POPBP
STORELP 4 [a]
JUMP ##Temp Jump 0##
LABEL ##Temp Jump 1##
POPL
POP
RETURN
Edit: Note I don't trust much the LSO assembler generator. Adding llOwnerSay((string)(16384-llGetFreeMemory())); at the beginning of the scripts, I got 356 for the first and 367 for the second. The diff above doesn't seem to justify a difference of 11 bytes.

Last edited by Sei Lisa; 03-18-2017 at 01:38 PM.
Sei Lisa is offline   Reply With Quote
1 User Said Thanks:
Old 03-20-2017, 07:29 AM   #16 (permalink)
Junior Member
 
Join Date: Mar 2017
Posts: 5
Again, thanks for additional info!

Speaking of speed, safety and overall good practices, I have another question.

what is preferred thing to do for example, I filter listen or link_message events, depending on what I am doing, and what would be considered safer/better/cleaner? (simple example without much planning just to get a picture if its not clear enough)

this
PHP Code:
executeCmd(string cmd) {
    if (
cmd == "action1") {
       
// do something here
    
} else if ...
}

link_message(integer sender_numinteger numstring strkey id){
    
executeCmd(str);

or simply do that in listen or link_message event directly like
PHP Code:
link_message(integer sender_numinteger numstring strkey id){
    if (
str == "action1") {
     
// do something 
    
}

Buzdovan is offline   Reply With Quote
Old 03-20-2017, 09:04 AM   #17 (permalink)
Senior Member
 
Sei Lisa's Avatar
My first name is Sei
 
Join Date: Aug 2013
Posts: 172
My Mood:
Talking about general programming practices, the first one is more versatile and is certainly recommended in most situations. It enables you to issue commands from other sides of the script, which may be desirable.

But if you're very pressed for memory, and you're sure you won't need to execute any actions from anywhere else in the script, you'll want the second solution, as creating a user function in LSL takes 300-400 bytes and has a big memory overhead on every call.
Sei Lisa is offline   Reply With Quote
1 User Said Thanks:
Old 03-20-2017, 09:07 AM   #18 (permalink)
Emergency Mustelid
 
Argent Stonecutter's Avatar
 
Join Date: Sep 2009
Posts: 18,737
Quote:
Originally Posted by Buzdovan View Post
Speaking of which, is there any particular case where you would WANT LSO over Mono?
Attachments.

When teleporting or crossing sim boundaries, LSO just gets copied. Mono needs to get re-compiled from CIL to machine code (just in time recompilation). This makes for more overhead, and more simulator lag. They've improved the process significantly but it's still measurable.

There are cases where the script is large or computationally intensive where that's impractical, but if you can I would recommend LSO for attachments.

Incidentally, that list hack would have broken on Mono scripts except I noticed the generated Mono code was being evaluated in a different order, and let LL know and they changed it to match LSO (at the cost of an extra swap instruction on basically every list operation, oh well) because there was too much existing code using the hack and it would have been a bloodbath. Good thing they were still including the LSL compiler in the viewer source back then.
__________________
Argent Stonecutter -- Skyhook Station -- Coonspiracy Store

"And now I'm going to show you something really cool."


The previous is a cybernetic datum published - in direct contravention of DoD Regulation #229RR3X3 - as being conducive to the physical, psychological and/or social well-being of the population.
Argent Stonecutter is offline   Reply With Quote
Old 03-20-2017, 01:30 PM   #19 (permalink)
Coin-operated
 
Qie Niangao's Avatar
 
Join Date: Nov 2007
Posts: 1,994
Quote:
Originally Posted by Buzdovan View Post
... what is preferred thing to do for example, I filter listen or link_message events, ...
I'll be contrarian here. I almost never define a function that's called from only one place in a script. It's just not worth the overhead, unless the function is fantastically complex or the event handler that contains it is fantastically complex, in which case it might be justified for readability.

There's another possibility specific to the question: by far the best filtering is done outside the script. That is, if you can specify a filter in the llListen call, that's vastly more efficient than matching text in a listen() handler within the script.

Tangentially, when matching a variable and a constant, you may find it handy to put the constant first, just so the frequent error of using the "=" assignment operator instead of the "==" comparison is caught by the compiler. The style is by no means universally adopted, but forcing myself to put them in that order is enough to deter using the wrong operator in the first place. (And that self-imposed discipline is particularly important in LSL, lacking true named constants.)
Qie Niangao is offline   Reply With Quote
1 User Agreed:
Old 03-20-2017, 07:24 PM   #20 (permalink)
Junior Member
 
Twisted Pharaoh's Avatar
Along with Athena, move also your hand
 
Join Date: Feb 2010
Posts: 2,137
My Mood:
SL Join Date: Yesterday
When you talk about optimization, it is space vs time. If you optimize for space you would use functions, and more generally reusable code, if you optimize for time then you inline code.

Now, the problem is that a larger program takes more memory and may slow down the system, so it is generally considered better to optimize for space.

When you want to optimize for time, you would use a tool called a profiler and identify which parts of the code take the more execution time, then you optimize that parts. Without a profiler you can print the time elapsed in seconds at various places in the program to get an idea.

Also, as the famous author Bertrand Meyer said, if your program has been built to run 1 time in 1 hour, if you spend 3 hours to make it run in 10 minutes, the time you have spent optimizing should be added to the total execution time, so 3 hours 10 minutes.

Quote:
Originally Posted by Qie Niangao View Post
I'll be contrarian here. I almost never define a function that's called from only one place in a script.
Yeah, rule of thumb is that if the same code is called 3 times or more, it's a good candidate for reusability (function, macro, template, or class, whatever).

With modern compilers, it's usually better to let the compiler perform the optimizations, because the best tactic may vary depending on the environment. So, if you write a function, the compiler may decide to inline the code. That's why you should write your code for readability first.

Now, I don't know if the LSL compilers have this level of sophistication.
Twisted Pharaoh is offline   Reply With Quote
Old 03-20-2017, 07:31 PM   #21 (permalink)
Emergency Mustelid
 
Argent Stonecutter's Avatar
 
Join Date: Sep 2009
Posts: 18,737
Since the compilation used to be in the viewer, the source to the compiler is available.

It's a pretty straightforward stack machine, with stack operands in the opposite order from basically everything else leading to the order of evaluation being right to left. The order of evaluation is still right to left because a resident named Strife Onizuka came up with some really dodgy but scarily popular optimizations that depend on it so (as I noted above) when they converted it into CIL they retained the same order of operations.
Argent Stonecutter is offline   Reply With Quote
1 User Said Thanks:
Old 03-20-2017, 07:46 PM   #22 (permalink)
Junior Member
 
Twisted Pharaoh's Avatar
Along with Athena, move also your hand
 
Join Date: Feb 2010
Posts: 2,137
My Mood:
SL Join Date: Yesterday
I wasn't expecting great stuff because I have noticed that for loops acted a bit strangely:

for (i=0; i <10 && !done; i++)

When 'done' is set to true at i=4, then the loop exits with i=5, because i++ seems to be executed before the condition.

LSL is like a box of chocolates...
Twisted Pharaoh is offline   Reply With Quote
Old 03-20-2017, 10:39 PM   #23 (permalink)
That Bitch

*SLU Supporter*
 
Void's Avatar
Innocent as far as you know
 
Join Date: Nov 2011
Location: Online
Posts: 14,580
My Mood:
SL Join Date: late 04 original account, mid 05 current
Quote:
Originally Posted by Twisted Pharaoh View Post
I wasn't expecting great stuff because I have noticed that for loops acted a bit strangely:

for (i=0; i <10 && !done; i++)

When 'done' is set to true at i=4, then the loop exits with i=5, because i++ seems to be executed before the condition.

LSL is like a box of chocolates...
that's actually correct behavior, the increment in a for loop happens just before the test, it's easier to understand if the read the for parameters as (starting condition, test condition at start, increment condition at the end).
Void is offline   Reply With Quote
1 User Agreed:
Old 03-20-2017, 10:47 PM   #24 (permalink)
Senior Member
 
Wanda Belinda's Avatar
 
Join Date: Oct 2016
Posts: 1,492
Quote:
Originally Posted by Void View Post
that's actually correct behavior, the increment in a for loop happens just before the test, it's easier to understand if the read the for parameters as (starting condition, test condition at start, increment condition at the end).
Is that a typo? Surely the increment is just after the test and before the body of the loop?
Wanda Belinda is offline   Reply With Quote
1 User Agreed:
Old 03-20-2017, 10:50 PM   #25 (permalink)
Senior Member
 
LoriClaremont's Avatar
This space for rent
 
Join Date: Jan 2011
Location: San Francisco area
Posts: 585
My Mood:
SL Join Date: 5/30/2009
Client: Firestorm
It's not a typo, a for loop is the equivalent to a while loop like this:

Code:
for (initial; test; incr) {
    body
}
is the same as:

Code:
initial
while (test) {
    body
    incr
}
LoriClaremont is offline   Reply With Quote
1 User Said Thanks:
1 User Agreed:
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are On




SEO by vBSEO