Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

a slight rant about if

Osgeld Barmy
Registered User
Join date: 22 Mar 2005
Posts: 3,336
10-19-2006 14:41
lateley ive seen alot of code flying about with a verry long list of just if statements, if statements get tested every event, have 25 if's doesnt matter if your script found what it was looking for in clause number 4, it still will test all 25

CODE

integer x;

default
{
touch_start(integer total_number)
{
if (x == 0) {llOwnerSay((string)x); ++x;}
if (x == 1) {llOwnerSay((string)x); ++x;}
if (x == 2) {llOwnerSay((string)x); ++x;}
if (x == 3) {llOwnerSay((string)x); ++x;}
if (x == 4) {llOwnerSay((string)x); ++x;}

llOwnerSay("done");
}
}


outputs
[14:28] Object: 0
[14:28] Object: 1
[14:28] Object: 2
[14:28] Object: 3
[14:28] Object: 4
[14:28] Object: done

but using
CODE

integer x;

default
{
touch_start(integer total_number)
{
if (x == 0) {llOwnerSay((string)x); ++x;}
else if (x == 1) {llOwnerSay((string)x); ++x;}
else if (x == 2) {llOwnerSay((string)x); ++x;}
else if (x == 3) {llOwnerSay((string)x); ++x;}
else if (x == 4) {llOwnerSay((string)x); ++x;}

llOwnerSay("done");
}
}


outputs
[14:28] Object: 0
[14:28] Object: done
next touch
[14:28] Object: 1
[14:28] Object: done
next touch
[14:28] Object: 2
[14:28] Object: done
next touch
[14:28] Object: 3
[14:28] Object: done
next touch
[14:28] Object: 4
[14:28] Object: done

whats it mean?

it stops testing once it has found a valid (true) result, in my statement with 25 if's once it finds what it needs it jumps out of the loop to move on to the rest of the event (rather they be llfunctions or another if else if block) so if it returns true on if statement # 4 the other 21 are not tested

else if's are your buddies and it saves everyone some cycles :)
Vares Solvang
It's all Relative
Join date: 26 Jan 2005
Posts: 2,235
10-19-2006 16:51
I've seen people use else if in their code before, but never really knew why. Thanks for clearing this up, I will keep it in mind from now on. :)

Maybe you should put a little blurb in the WIKI about it.
_____________________
Ralph Doctorow
Registered User
Join date: 16 Oct 2005
Posts: 560
10-19-2006 16:59
Well, keep in mind that LSL only allows about 7 to 10 levels of else if depending on what else is in the script. Beyond that it won't compile.

For things where I'd like to use a switch statement for I generally use a series of if statements with a jump statement to skip the rest.

Unfortunately, this sometimes has compile problems too if things get too complex.
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
10-19-2006 17:28
I was thinking of something along these lines the other day. WHat about carrying it one step further:

CODE

integer x;

default
{
touch_start(integer total_number)
{
if (x >= 0 && x <= 5){
if (x == 0) {llOwnerSay((string)x); ++x;}
else if (x == 1) {llOwnerSay((string)x); ++x;}
else if (x == 2) {llOwnerSay((string)x); ++x;}
else if (x == 3) {llOwnerSay((string)x); ++x;}
else if (x == 4) {llOwnerSay((string)x); ++x;}
else if (x == 5) {llOwnerSay((string)x); ++x;}}
else if (x >= 6 && x <= 10){
if (x == 6) {llOwnerSay((string)x); ++x;}
else if (x == 7) {llOwnerSay((string)x); ++x;}
else if (x == 8) {llOwnerSay((string)x); ++x;}
else if (x == 9) {llOwnerSay((string)x); ++x;}
else if (x == 10) {llOwnerSay((string)x); ++x;}}
else if (x >= 11 && x <= 15){
if (x == 11) {llOwnerSay((string)x); ++x;}
else if (x == 12) {llOwnerSay((string)x); ++x;}
else if (x == 13) {llOwnerSay((string)x); ++x;}
else if (x == 14) {llOwnerSay((string)x); ++x;}
else if (x == 15) {llOwnerSay((string)x); ++x;}}

llOwnerSay("done");
}
}

It would seem logical that it would save some processor time and also allow a person to compile more if's.
_____________________
I (who is a she not a he) reserve the right to exercise selective comprehension of the OP's question at anytime.
From: someone
I am still around, just no longer here. See you across the aisle. Hope LL burns in hell for archiving this forum
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
10-19-2006 17:48
It is quite a bit faster this way:
CODE

integer x;

default
{
state_entry()
{
llResetTime();
if (x >= 0 && x <= 5){
if (x == 0) {llOwnerSay((string)x); ++x;}
else if (x == 1) {llOwnerSay((string)x); ++x;}
else if (x == 2) {llOwnerSay((string)x); ++x;}
else if (x == 3) {llOwnerSay((string)x); ++x;}
else if (x == 4) {llOwnerSay((string)x); ++x;}
else if (x == 5) {llOwnerSay((string)x); ++x;}}
else if (x >= 6 && x <= 10){
if (x == 6) {llOwnerSay((string)x); ++x;}
else if (x == 7) {llOwnerSay((string)x); ++x;}
else if (x == 8) {llOwnerSay((string)x); ++x;}
else if (x == 9) {llOwnerSay((string)x); ++x;}
else if (x == 10) {llOwnerSay((string)x); ++x;}}
else if (x >= 11 && x <= 15){
if (x == 11) {llOwnerSay((string)x); ++x;}
else if (x == 12) {llOwnerSay((string)x); ++x;}
else if (x == 13) {llOwnerSay((string)x); ++x;}
else if (x == 14) {llOwnerSay((string)x); ++x;}
else if (x == 15) {llOwnerSay((string)x); ++x;}}

llOwnerSay("done");
float elapsed = llGetTime();
llOwnerSay((string)elapsed);
state next;
}
}
state next{
state_entry(){
state default;
}
}

[17:42] Object: 0
[17:42] Object: done
[17:42] Object: 0.022222
[17:42] Object: 1
[17:42] Object: 0.044763
[17:42] Object: done
[17:42] Object: 2
[17:42] Object: done
[17:42] Object: 0.023070
[17:42] Object: 3
[17:42] Object: done
[17:42] Object: 0.022647
[17:42] Object: 4
[17:42] Object: done
[17:42] Object: 0.022400
[17:42] Object: 5
[17:42] Object: done
[17:42] Object: 0.044300
[17:42] Object: 6
[17:42] Object: done
[17:42] Object: 0.021598
[17:42] Object: 7
[17:42] Object: done
[17:42] Object: 0.044201
[17:42] Object: 8
[17:42] Object: done
[17:42] Object: 0.022307
[17:42] Object: 9
[17:42] Object: done
[17:42] Object: 0.044916
[17:42] Object: 10
[17:42] Object: done
[17:42] Object: 0.020590
[17:42] Object: 11
[17:42] Object: done
[17:42] Object: 0.021777
[17:42] Object: 12
[17:42] Object: done
[17:42] Object: 0.023007
[17:42] Object: 13
[17:42] Object: done
[17:42] Object: 0.044609
[17:42] Object: 14
[17:42] Object: done
[17:42] Object: 0.021863
_____________________
I (who is a she not a he) reserve the right to exercise selective comprehension of the OP's question at anytime.
From: someone
I am still around, just no longer here. See you across the aisle. Hope LL burns in hell for archiving this forum
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
10-19-2006 17:49
CODE

integer x;

default
{
state_entry()
{
if (x == 0) {llOwnerSay((string)x); ++x;}
else if (x == 1) {llOwnerSay((string)x); ++x;}
else if (x == 2) {llOwnerSay((string)x); ++x;}
else if (x == 3) {llOwnerSay((string)x); ++x;}
else if (x == 4) {llOwnerSay((string)x); ++x;}
else if (x == 5) {llOwnerSay((string)x); ++x;}
else if (x == 6) {llOwnerSay((string)x); ++x;}
else if (x == 7) {llOwnerSay((string)x); ++x;}
else if (x == 8) {llOwnerSay((string)x); ++x;}
else if (x == 9) {llOwnerSay((string)x); ++x;}
else if (x == 10) {llOwnerSay((string)x); ++x;}
else if (x == 11) {llOwnerSay((string)x); ++x;}
else if (x == 12) {llOwnerSay((string)x); ++x;}
else if (x == 13) {llOwnerSay((string)x); ++x;}
else if (x == 14) {llOwnerSay((string)x); ++x;}
else if (x == 15) {llOwnerSay((string)x); ++x;}

llOwnerSay("done");
float elapsed = llGetTime();
llOwnerSay((string)elapsed);
state next;
}
}
state next{
state_entry(){
state default;
}
}

[17:45] Object: 0
[17:45] Object: done
[17:45] Object: 0.023403
[17:45] Object: 1
[17:45] Object: done
[17:45] Object: 0.067865
[17:45] Object: 2
[17:45] Object: done
[17:45] Object: 0.134869
[17:45] Object: 3
[17:45] Object: done
[17:45] Object: 4
[17:45] Object: done
[17:45] Object: 0.247001
[17:45] Object: 5
[17:45] Object: done
[17:45] Object: 0.291390
[17:45] Object: 6
[17:45] Object: done
[17:45] Object: 0.357884
[17:45] Object: 7
[17:45] Object: done
[17:45] Object: 0.424360
[17:45] Object: 8
[17:45] Object: done
[17:45] Object: 0.494238
[17:45] Object: 9
[17:45] Object: done
[17:45] Object: 0.558942
[17:45] Object: 10
[17:45] Object: done
[17:45] Object: 0.625446
[17:45] Object: 11
[17:45] Object: done
[17:45] Object: 0.692779
[17:45] Object: 12
[17:45] Object: done
[17:45] Object: 0.759369
[17:45] Object: 13
[17:45] Object: done
[17:45] Object: 0.826195
[17:45] Object: 14
[17:45] Object: done
[17:45] Object: 0.893038
[17:45] Object: 15
[17:45] Object: done
[17:45] Object: 0.960032
_____________________
I (who is a she not a he) reserve the right to exercise selective comprehension of the OP's question at anytime.
From: someone
I am still around, just no longer here. See you across the aisle. Hope LL burns in hell for archiving this forum
Osgeld Barmy
Registered User
Join date: 22 Mar 2005
Posts: 3,336
10-19-2006 22:15
CODE

integer x;
float total_time;
integer bean_counter;

output() {llOwnerSay((string)x); ++bean_counter;}

default
{
state_entry()
{
llResetTime();
if (x >= 0 && x <= 7)
{
++bean_counter;
if (x == 0) {output();}
else if (x == 1) {output();}
else if (x == 2) {output();}
else if (x == 3) {output();}
else if (x == 4) {output();}
else if (x == 5) {output();}
else if (x == 6) {output();}
else if (x == 7) {output();}
}

else if (x >= 8 && x <= 15)
{
++bean_counter;
if (x == 8) {output();}
else if (x == 9) {output();}
else if (x == 10) {output();}
else if (x == 11) {output();}
else if (x == 12) {output();}
else if (x == 13) {output();}
else if (x == 14) {output();}
else if (x == 15) {output();}
}


else if (x >= 16 && x <= 23)
{
++bean_counter;
if (x == 16) {output();}
else if (x == 17) {output();}
else if (x == 18) {output();}
else if (x == 19) {output();}
else if (x == 20) {output();}
else if (x == 21) {output();}
else if (x == 22) {output();}
else if (x == 23) {output();}
}

else
{
++bean_counter;
if (x == 24) {output();}
else if (x == 25) {output();}
else if (x == 26) {output();}
else if (x == 27) {output();}
else if (x == 28) {output();}
else if (x == 29) {output();}
else if (x == 30) {output();}
else if (x == 31) {output();}
}

if (x < 32)
{
++x;
float elapsed = llGetTime();
llOwnerSay("request took "+(string)elapsed+" seconds");
total_time += elapsed;
++bean_counter;
state loop;
}

else
{
++bean_counter;
llOwnerSay(
"total time to access "
+ (string)bean_counter
+ " if, else if, and else tests in squence = "
+ (string)total_time
+ " seconds"
);
}
}
}

state loop
{
state_entry()
{
state default;
}
}


average
CODE

Object: 0
Object: request took 0.156732 seconds
Object: 1
Object: request took 0.156520 seconds
Object: 2
Object: request took 0.134583 seconds
Object: 3
Object: request took 0.156555 seconds
Object: 4
Object: request took 0.156686 seconds
Object: 5
Object: request took 0.156538 seconds
Object: 6
Object: request took 0.156833 seconds
Object: 7
Object: request took 0.223634 seconds
Object: 8
Object: request took 0.178999 seconds
Object: 9
Object: request took 0.224335 seconds
Object: 10
Object: request took 0.156799 seconds
Object: 11
Object: request took 0.134186 seconds
Object: 12
Object: request took 0.134211 seconds
Object: 13
Object: request took 0.134168 seconds
Object: 14
Object: request took 0.156575 seconds
Object: 15
Object: request took 0.156565 seconds
Object: 16
Object: request took 0.156501 seconds
Object: 17
Object: request took 0.156495 seconds
Object: 18
Object: request took 0.156440 seconds
Object: 19
Object: request took 0.223521 seconds
Object: 20
Object: request took 0.156494 seconds
Object: 21
Object: request took 0.157486 seconds
Object: 22
Object: request took 0.246008 seconds
Object: 23
Object: request took 0.223812 seconds
Object: 24
Object: request took 0.246055 seconds
Object: 25
Object: request took 0.156566 seconds
Object: 26
Object: request took 0.223632 seconds
Object: 27
Object: request took 0.157045 seconds
Object: 28
Object: request took 0.156539 seconds
Object: 29
Object: request took 0.156567 seconds
Object: 30
Object: request took 0.246136 seconds
Object: 31
Object: request took 0.223631 seconds
Object: total time to access 98 if, else if, and else tests in squence = 5.616847 seconds


i dont really suggest it tho, 99% of the time theres a better way to deal with it
ed44 Gupte
Explorer (Retired)
Join date: 7 Oct 2005
Posts: 638
10-19-2006 22:57
Some of my larger pieces of code run out of compiler stack space and I would need to modify my code to not have else statements, using return statements instread, jumping prematurely out of a function, so the OP's code becomes:
CODE

integer x;

doit() {
if (x == 0) {llOwnerSay((string)x); ++x; return;}
if (x == 1) {llOwnerSay((string)x); ++x; return;}
if (x == 2) {llOwnerSay((string)x); ++x; return;}
if (x == 3) {llOwnerSay((string)x); ++x; return;}
if (x == 4) {llOwnerSay((string)x); ++x; return;}
}



default
{
touch_start(integer total_number)
{
doit ();
llOwnerSay("done");
}
}

Hopefully we can abandon this work around when we get mono!!
Zeera Xi
Real Join Date: Mid '05
Join date: 21 Sep 2006
Posts: 54
10-20-2006 05:02
From: ed44 Gupte
Hopefully we can abandon this work around when we get mono!!


LSL type coding will stay the same once we get mono. The only difference is the backend on how the sim executes the code.

Proportionally it would mean that you still have to use such work arounds if you still care about process speed.
Ohforf Uram
n00b
Join date: 27 Jun 2006
Posts: 82
10-20-2006 05:44
*looks at Benchmark Results* :eek:

The slowness and memory limits of LSL are a real Pain.
It reminds me of a BASIC Interpreter running on a old
Home Computer or Microcontroller.
Is there no hope to get something better with mono ?
Running thousands of Processes/Tasks/Threads works just
fine on a midrange PC - OK, these are 'real' compiled
Executables, not some java style bytecode garbage.

I dont really use .net stuff, but I'm sure its not _that_ bad.
(i still prefer C/C++ and Win32 API for everyday Work)
_____________________
Eloise Pasteur
Curious Individual
Join date: 14 Jul 2004
Posts: 1,952
10-20-2006 11:06
I'd suggest hunting for Babbage's posts, since he's the person doing it. But, to sum up again:

When (or if) SL moves over to mono support for lsl it will be running lsl ONLY. There are a number of hacks and squishes and bodges (that's a paraphrase of Babbage's words, but I don't think an unfair one, sorry if you disagree Babbage) to make mono fit within the SL framework.

There is, longer term, the possibility that SL will allow coding in other languages under mono. Given I remember attending a talk by Babbage over 18 months ago in which "Mono was close" holding your breath and hoping for your favourite other language to replace lsl within SL... I wouldn't.
_____________________
Eloise's MiniMall
Visit Eloise's Minimall
New, smaller footprint, same great materials.

Check out the new blog
Jopsy Pendragon
Perpetual Outsider
Join date: 15 Jan 2004
Posts: 1,906
10-20-2006 11:31
Of course, if it doesn't make your code completely unreadable...
don't bother use if at all! :D

CODE


default {
touch_start(integer total_number) {
llOwnerSay("default"); state one;
}
}

state one {
touch_start(integer total_number) {
llOwnerSay("one"); state two;
}
}

state two {
touch_start(integer total_number) {
llOwnerSay("two"); state three;
}
}

state three {
touch_start(integer total_number) {
llOwnerSay("three"); state default;
}
}
Osgeld Barmy
Registered User
Join date: 22 Mar 2005
Posts: 3,336
10-20-2006 20:13
what happens when the user wants to jump from state two back to one, or from two to 4, or from 1 to 32

altho quite usefull and valid, its a slightly different bear from the examples above :)
Osgeld Barmy
Registered User
Join date: 22 Mar 2005
Posts: 3,336
10-20-2006 21:09
From: ed44 Gupte
Some of my larger pieces of code run out of compiler stack space and I would need to modify my code to not have else statements, using return statements instread, jumping prematurely out of a function, so the OP's code becomes:
CODE

integer x;

doit() {
if (x == 0) {llOwnerSay((string)x); ++x; return;}
if (x == 1) {llOwnerSay((string)x); ++x; return;}
if (x == 2) {llOwnerSay((string)x); ++x; return;}
if (x == 3) {llOwnerSay((string)x); ++x; return;}
if (x == 4) {llOwnerSay((string)x); ++x; return;}
}



default
{
touch_start(integer total_number)
{
doit ();
llOwnerSay("done");
}
}




aye ive done this also many of times, ending each clause with a return is AFAIK the most propper way of handling it
Zebra North
Broadly Offensive
Join date: 7 May 2006
Posts: 48
10-21-2006 03:50
Jesse Barnett was on the right track... what you're heading towards is a hard-coded binary search. A binary search has O(log(n)) execution time, whereas a linear search (testing every case until you find the right one) has O(n) time. This basically means that as 'n' (the number of cases you need to differentiate) becomes larger, the time taken to execute a binary search grows much more slowly than for a linear search.

Here's the code for a binary search for 8 items. The saving for searching 8 items isn't really that much (average 3 tests vs 4) - benchmark it for 16 if you want to see a big difference. (average 4 tests vs 8).

CODE

if (x < 4)
if (x < 2)
if (x < 1)
DoSomething(0);
else
DoSomething(1);
else
if (x < 3)
DoSomething(2);
else
DoSomething(3);
else
if (x < 6)
if (x < 5)
DoSomething(4);
else
DoSomething(5);
else
if (x < 7)
DoSomething(6);
else
DoSomething(7);


As you can see, you need 3 tests to get to any answer. If this was a linear search (if, else if, else if), you would need up to 8 tests. If there were 16 options, the binary search would take 4 tests (log_base_2(16) = 4), but the linear search would take up to 16.


ps, something to remember if you're using a linear search: this is pretty obvious, but if you know that one input is more probable than another, put the most probable one first.
Ohforf Uram
n00b
Join date: 27 Jun 2006
Posts: 82
10-21-2006 07:03
From: Zebra North
Jesse Barnett was on the right track... what you're heading towards is a hard-coded binary search...


You win ! :)
Fast, readable... great !
_____________________
Stephen Zenith
Registered User
Join date: 15 May 2006
Posts: 1,029
10-21-2006 09:32
Of course, this would all be moot if LSL had some type of switch statement.
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
10-21-2006 11:01
Just had to play with this after drinking a couple of cups of coffee this morning.

16 itinerations:

Linear search; .375 secs & 888 bytes of memory used.

Binary search; .355 secs & 795 bytes of memory used.

So I would have to agree. Zebra wins the Golden Scripter Award on this one. It is more readable, faster and uses less memory.
_____________________
I (who is a she not a he) reserve the right to exercise selective comprehension of the OP's question at anytime.
From: someone
I am still around, just no longer here. See you across the aisle. Hope LL burns in hell for archiving this forum
Zebra North
Broadly Offensive
Join date: 7 May 2006
Posts: 48
10-21-2006 11:43
w00t! Where do I pick up my cash prize...? :D

And yep, a switch statement would be nice... can we have one, LL? Please? heheh ;)
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
10-21-2006 13:36
From: Zebra North
w00t! Where do I pick up my cash prize...? :D


You should be receiving a life time supply of "Hello Avatar" scripts and a years subscription to "We have no other life" magazine shortly :-)
_____________________
I (who is a she not a he) reserve the right to exercise selective comprehension of the OP's question at anytime.
From: someone
I am still around, just no longer here. See you across the aisle. Hope LL burns in hell for archiving this forum