Gosub or functions?

Blitz3D Forums/Blitz3D Beginners Area/Gosub or functions?

Hansie(Posted 2003) [#1]
@all

Whats the best? Gosub/Return or calling a function? which is the fastest, why and how?


CS_TBL(Posted 2003) [#2]
Use functions.. period!

Once you are used to functions you never want to go back to gosub thingies. Not to mention the arguements you can send with to function.


puki(Posted 2003) [#3]
Yeh, I agree Functions rule - but which is faster - are there pros and cons in different uses of them? It's an interesting question.


Hansie(Posted 2003) [#4]
@puki

exactly, I am interested in the "nitti-gritty" details of differences in speed etc ...


ford escort(Posted 2003) [#5]
gosubs seems faster than functions

try this code :p
[/code]
Graphics 800,600,0,2
t=MilliSecs()
For a=1 To 1000000
Gosub blah
Next
Text 0,0,MilliSecs()-t
Flip
t=MilliSecs()
For a=1 To 1000000
bloh()
Next
Text 0,10,MilliSecs()-t
Flip
WaitKey
End
.blah
Return
Function bloh()
End Function
[/code]
results are
8
12
on my system debug off

but remember that you can use the same vars in all of your functions as they are locals, in oposition of the gosub that you have to use variables that are available in the entire program, also you can't pass values with gosub, you have to put them in the vars before.


Hansie(Posted 2003) [#6]
@ford escort

good input!


Shambler(Posted 2003) [#7]
Interesting but you are hardly going to have a million gosubs or function calls per frame so the difference in performance in a game will be negligable.

Functions allow you to structure your code making it easier to debug and understand, for these reasons I've not used a gosub ever in Blitz...or any other language I can think of that has functions.

Gosub is one of those commands that should be banished from any programming language, along with its partner in crime goto =)


GfK(Posted 2003) [#8]
I've used GoTo before.

If I have a choice between using a GoTo, or coding for 2 hours to avoid having to use a GoTo and still get the same result, I know what I'd rather do.


Ross C(Posted 2003) [#9]
Yeah, gosubs are useful. If you wanna have a bit of code that does a job without input, then i use gosubs. Nothing wrong with it, unless your a code snob.

Goto is extremely useful too. If you have a large section of code you don't wanna run, put a label at the end of it, and use goto to skip bits of the code. :)


soja(Posted 2003) [#10]
Gfk, if you have to spend two hours to avoid using a Goto, I'd hate to see your code! ;)


Ross C(Posted 2003) [#11]
I think he meant if he had the choice, he'd use goto ;) So would i :)


GfK(Posted 2003) [#12]
I think he meant if he had the choice, he'd use goto ;) So would i :)
Yes.


Jeremy Alessi(Posted 2003) [#13]
I use Gosub's very often too. If it's a very general routine then I use a Gosub just to keep code clean and separate. If it's a very specific task that should be separated comepletely from the rest of my data I use a function. Both are in your toolbox and both should be used.


Hansie(Posted 2003) [#14]
@all

Goto's can be quite OK. Look at this code snippet:

		For i = 1 To bot_numchars
    		bot_currentchar = Asc(Mid(FadeTextBot$,i,1))
		If bot_currentchar = bot_space Then : Goto skipbot : End If
		bot_currentchar = bot_currentchar - 65
		DrawImage (vh_fadeintro_fnt,bot_tempx,bot_tempy,bot_currentchar)
.skipbot	bot_tempx = (bot_tempx+vh_fadeintro_fntwidth) : Next


In the code above we print bitmap characters to the screen, and if a SPACE character ( ) is needed to be printed, we print nothing, but increment the X position to align the next position. This also saves having an empty SPACE character in the bitmap font ...


Floyd(Posted 2003) [#15]
That code seems to be formatted for maximum unreadability.
Here it is neatened up:
For i = 1 To bot_numchars
    bot_currentchar = Asc(Mid(FadeTextBot$,i,1))
	If bot_currentchar = bot_space Then : Goto skipbot
	bot_currentchar = bot_currentchar - 65
	DrawImage (vh_fadeintro_fnt,bot_tempx,bot_tempy,bot_currentchar)
.skipbot
	bot_tempx = (bot_tempx+vh_fadeintro_fntwidth)
Next

I rarely use Goto because the code is usually clearer without it. For example:
For i = 1 To bot_numchars
    bot_currentchar = Asc(Mid(FadeTextBot$,i,1))
	If bot_currentchar <> bot_space
		bot_currentchar = bot_currentchar - 65
		DrawImage (vh_fadeintro_fnt,bot_tempx,bot_tempy,bot_currentchar)
	End If
	bot_tempx = (bot_tempx+vh_fadeintro_fntwidth)
Next



MSW(Posted 2003) [#16]
Gosubs are faster simply because nothing except a return memory pointer value is pushed onto the stack...

When you call a function (be it one you wrote or some of the ones built into Blitz, the CPU will push the passed variables onto the stack along with a "return" memory pointer so it knows where to go when the function is done...once the CPU gets to the function it pulls (pops) all those variables back off the stack for the function to use...when it hits the end of the function (or a return) it pops the "return memory address pointer" off the stack, pushes whatever return value set by the function (return 7 for example) back onto the stack and jumps to the memory location indicated by the "return memory address" and the program continues...if you didn't tell the function to return a specific value (like Return 7) then a NULL (zero) value is pushed onto the stack in place of it...

A gosub works in a simular manner...the "return to" pointer is pushed onto the stack, the CPU jumps to the gosub routine...then once done it pops the return value back off the stack and jumps to that location...no extra pushes/pops required, which is why it's a bit faster

A goto works in a manner simular to the JMP assembly instruction...indeed..be it a function, subroutine, or just a goto...they all use one of the JMP opcodes...however goto doesn't push anything onto the stack, and because of this it is faster then both functions and subroutines.

However if speed it your big concern then you shouldn't use any of these...the fastest code is always going to be strait inline stuff...no functions, no subroutines, no use of goto...this is because there can be a large varience in the amount of time it takes your CPU to process a JMP opcode...this is because the location in your code that the CPU is trying to JMP to may not yet exist in the processors cache, so the processor must wait for it to load in from system memory (this is called a "cache hit", as in you take a speed hit from haveing the CPU waiting around several cycles waiting on the correct bit of code).

essentualy functions are just more advanced subroutines, which are just more advanced ways of haveing goto.


CS_TBL(Posted 2003) [#17]
I'd say that there's another kind of speed that is important.. "development-speed". So, maybe gosubs are a little bit faster.. but in these days I'd say that development-time is way more important since that actually costs you or your company money. So, again: functions!

I use goto rarely, but when I use it, it's because blitz has no block-commenting.


turtle1776(Posted 2003) [#18]
@MSW

Thank you for that very informative, high quality post!

Personally, I agree with Shambler that the speed difference between functions and gosubs is negligible and that the fact that functions make you pass in values can make them a bit easier to debug and understand. On the other hand, if you decide not to pass in a zillion variables and use globals instead, it will be equally unreadable. Also, you can't declare a variable as global inside a function.

As for goto, one very useful feature is that they can be used inside functions. I find myself using them to skip to the end of a function to do cleanup things before exiting.

Overall, I say use whatever works for you.


Neo Genesis10(Posted 2003) [#19]
Gosub is the spawn of Satan! Never really liked it much, and probably never will. Didnt even use it way back when on the ancient Acorn Electron (cos functions made my code look pretty). I like them for the following reasons:

1) Tidy code is easier to understand and to debug. Functions make it tidier.
2) Recursive functions are seriously useful, especially when dealing with parent and child entities in B3D.
3) Large numbers of Gosubs can get very confusing very quickly.

Just thought I'd add my input.


Hansie(Posted 2003) [#20]
@all

good, valid feedback


eBusiness(Posted 2004) [#21]
Don't see why a gosub should make code confusing, it is written just like a function, and can be used so with a speed increase.


ford escort(Posted 2004) [#22]
well for exemple you have a function that write hello world to a graphic buffer
function heloworld(buffer)
 setbuffer buffer
 text 10,10,"hello world"
end function


you can call it later for multiple buffers like that
helloworld(imagebuffer(mypic1)
helloworld(backbuffe())
helloworld(imagebuffer(mypic2))


to do the same things with gosub the code may like the same
.helloworld
setbuffer buffer
text 10,10,"hello world"
return


but more difficult to use
buffer=imagebuffer(mypic1):gosub helloworld
buffer=backbuffer():gosub helloworld
buffer=imagebuffer(mypic2):gosub helloworld


and you have to remember the name of the variables used in the 'gosub'

so quicker but more difficult to code :)


LostCargo(Posted 2004) [#23]
10 if x > 10 then
20 gosub 160
25 else if x < 10 then
30 gosub 180
50 end if

this case wont catch if it = 0 then your code executes as sequentially
oh but wait it gets better!

60 //do stuff here
70 gosub 25

oh but wait. what if we add 1 line above line 25. Now we have to go through allllllll of our bloody code to update the goto statements. (depending if you have declaired line numbers or not.

GO SUBS COMPOND SPAGETTI CODING>

im sorry eBusiness. but i cant agreee. obviously you havent worked on any large systems that use more than 40 lines of code .


GO SUB USERS SHOULD BE NAILED TO A TREE!
sorry for the excessive emotion on this one. But try spending !!2 years!! updating code on a project that someone decided to use incorrect gosubs with includes. then talk to me about how it shouldnt '..make things confusing...'

!!!!!!arg... !!!!!!

im so frustrated for even reading that 'use go subs they are cool' response... lol

sorry if i offended anyone.


Ross C(Posted 2004) [#24]
Ppl who use gosubs like that deserve all they get :) If used properly, there not a problem, as, as i said, there used for a purpose that doesn't require input. :)


Shambler(Posted 2004) [#25]
Lol @baudspeed =) I agree completely though, just nice to see someone so passionate about it =)


Curtastic(Posted 2004) [#26]
@Baudspeed

OH NO! Now I will have to change all of my 30-year-old or just retarded code that uses LINE NUMBERS to gosub! I was sure it was a brilliant way to code as you can see that all of the code in the code archives looks like that, just with functions instead.

now im off to "COMPOND?" on my dinasaur-basic


LostCargo(Posted 2004) [#27]
@Coorae
wow brilliant argument for using gosubs. coorae. bravo.bravo.bravo.
<insert crickets chirping here>


Curtastic(Posted 2004) [#28]

this case wont catch if it = 0 then your code executes as sequentially



apparently you dont know so ... with a gosub you return to where it was called from. this is not the same as goto. Assuming the gosubs return (the coder is somewhat competent), the execution will always pass through that code no matter what x is.


LostCargo(Posted 2004) [#29]
coorae. thanks for backing your opinion up. i can see what you are getting at. But i would *fire* a programmer on the spot if they were working in a language that allowed functions but used gosubs.
I spent too much time supporting garbage code. I have seen developers leave companies because they wrote garbage code and their jobs were to support it. Then the next guy who comes through has no doc because you really honestly cant document gosub/gotos.

I'm not stating this again so that i can try and change your opinion. You have an opinon. I just don't agree with it. I appreciate the fact that you did back it up though. Thanks.


Curtastic(Posted 2004) [#30]
It just seems like you were talking about GOTO.
Most gosubs that work just like a function are not any harder to document than a function that could be in its place.


I'm not stating this again so that i can try and change your opinion. You have an opinon. I just don't agree with it.


My only shown opinions were that I dont like that your argument was not well made, and I dont like jumping based on line numbers either.
Im glad you took it well.
I used to use gosub until I found that functions are better in the long run. That is my opinion, I now rarely use gosub or goto.


eBusiness(Posted 2004) [#31]
Baudspeed, line numbers are dead, today we use labels, like this:
Repeat
  Dostuff
  Gosub dootherstuff
Forever
End

.dootherstuff
  Doing stuff
Return
See, not much different from a function, only it's faster :)


AbbaRue(Posted 2004) [#32]
I have always found Gosubs easyer to follow than functions.
In ford escort's egs.

buffer=imagebuffer(mypic1):gosub helloworld
I know exactly what the code is doing at this point

helloworld(imagebuffer(mypic1)
But I don't have a clue what is going on here.

The gosub code is self explanitory. When I use a function
I always have to comment it so I know what the line of code is really doing.
The only thing harder to follow then functions is Includes.
Now includes really confuse a program.
Because then you have to load up the include file in a seperate window
and search for your varibles.
Some includes I have seen include other includes, which include other includes.
You end up searching through 10 files to find what a varible stands for.
No wonder software is so expensive these days.


CS_TBL(Posted 2004) [#33]
repeat
  DrawPlayer()
forever


seems clear to me.. not less clear than:

repeat
  Gosub DrawPlayer
forever


I've no problems anymore with includes since I know how to make my own stuff highlight using that declr trick.

and what about:

repeat
  DrawPlayer(100,100)
forever


compared to:

repeat
  PlayerX=100:PlayerY=100:gosub DrawPlayer
forever


The main reason I like functions over gosubs is that functions look like other commands. Imagine the Rect command using a gosub:

RectX=0:RectY=0:RectWIdth=100:RectHeight=40:RectFill=true:gosub Rect

I use long variablenames since they need to be globals, and common stuff like x and y are usually already in use.

and now as a function:

Rect 0,0,100,40,true

By using functions all stuff looks uniform.

... 2ct.


Paul "Taiphoz"(Posted 2004) [#34]
PS. I dont use goto's or gosubs. Not because I dont like them, just that Iv had good coding style shoved down me from college and UNI so its kinda habbit not to use em.


FlameDuck(Posted 2004) [#35]
The key here is variable scope. You should preferably use functions, because that way any larger or more complicated subroutines use their own 'local' variables, which means they have *no* chance of screwing up you 'main' variables. Ofcourse if you're not carefull you can still screw up Globals, arrays and types, but generally using functions is safer, particularilly if you're writting a long and/or complex subroutine.

I haven't used goto/gosub for at least a decade. It really holds no advantages over functions/methods. Speed difference is negliable, and certainly not worth the possible stabilty trade-off.


turtle1776(Posted 2004) [#36]
>> The key here is variable scope

Good point, FlameDuck. I must admit, however, that I still use Gosub for short programs, mostly because I use a handful of variables that I want to use globally, and I can't be bothered declaring them as such separately (poor excuse) or passing them into the function.

If I do anything serious or complicated I use functions.

I still think Goto has certain limited uses on rare occasions (like inside a function, for example). But its use should be minimized or you end up with confusing spaghetti code that is difficult to understand or debug.

>>The way I see it. if it works use it. NO programmer should be worried about how some one else is going to think of them because of their code.

Amen, Yavin. Unless you are working for someone else and perceptions matter. But we're mostly hobbyists around here.


AbbaRue(Posted 2004) [#37]
I have done some asm programming, over the years.
And I know that all functions are actually converted into
gosubs or in asm terms calls to subroutines. And all
branching functions are converted into some type of jmp.
eg jle, jne, jeq, jz. I find goto invaluable when debuging.
To comment out areas or pass over suspected problem areas.
Because of my asm programming skills I like gosubs because they are used exactly like a call in asm. you push your paramaters on the stack and then call the subroutine.
That is the way the windows apl works too.


Hansie(Posted 2004) [#38]
@AbbaRue

just as you I have programmed Assembler for DECADES and also tend to use gosub/goto primarily for debugging purposes


FlameDuck(Posted 2004) [#39]
Having programmed Assembler has nothing to do with it (I still program assembler on occasion, mostly when absolutely nessecary). Functions are *not* just glorified gosubs (or jumps/branches) because they have their own namespace. I find block commenting much more useful than gotos for debuging purposes.
That is the way the windows apl works too.
The Windows API, and indeed *most* API's are objective in nature. Thats how OOP originated. Engineers at Xerox PARC, while inventing the GUI, also invented OOP (more specificly SmallTalk) to make it all manageable.