[Gambas-user] Are GoSubs efficient?

nando_f at nothingsimple.com nando_f at nothingsimple.com
Mon Apr 22 23:51:12 CEST 2019


I have been using GOSUB as a common code subroutine when I don't need to pass variables.
It's almost like having an anonymous function using the existing local vars.
It works much faster overall especially if you do a lot them and time matters.

I also use them for making PDF's in a function to do little repeated work.
They also help me with user input cleanup.
I believe there is a place for their use.

I normally place/write them at the end of a function



---------- Original Message -----------
From: Cedron Dawg <cedron at exede.net>
To: user <user at lists.gambas-basic.org>
Sent: Mon, 22 Apr 2019 16:41:46 -0400 (EDT)
Subject: Re: [Gambas-user] Are GoSubs efficient?

> Thanks, this was really helpful and extremely informative.
> 
> ----- Original Message -----
> From: "Tobias Boege" <taboege at gmail.com>
> 
> At the bytecode level, GoSub compiles to a single instruction, whereas
> a call is at least two. This nonsensical piece of code
> 
>   Public Function f(a As Integer, b As Integer) As Integer
>   _Next:
>     Dec a
>     GoSub _Next
>     f(a, b - 1)
>   End
> 
> for example becomes
> 
>   0000 :  02FE            PUSH PARAM -2
>   0001 :  AFFF            ADD QUICK -1
>   0002 :  0AFE            POP PARAM -2
>   0003 :  2300 FFFB       GOSUB 0000
>   0005 :  B803            PUSH FUNCTION f
>   0006 :  02FE            PUSH PARAM -2
>   0007 :  02FF            PUSH PARAM -1
>   0008 :  AFFF            ADD QUICK -1
>   0009 :  1C02            CALL (2)
>   0010 :  1A01            DROP (1)
>   0011 :  1002            RETURN (2)
> 
> As for the runtime overhead, GOSUB at [1] is literally saving some context,
> including the instruction pointer, followed by a GOTO. The CALL instruction
> at [2] is obviously more complicated.
> 
> Whereas the GoSub target offset is encoded in the instruction, pretty much
> every form of CALL requires some kind of lookup in the current context and
> parameter checks.
> 
> Finally, running these two, hopefully comparable enough [*], implementations
> of the identity function:
> 
>   Public Function f(b As Integer) As Integer
>     Dim a As Integer
>   _Inc:
>     Inc a
>     Dec b
>     If b Then GoSub _Inc
>     Return a
>   End
> 
>   Public Function g(b As Integer) As Integer
>     If Not b Then Return b
>     Return 1 + g(b - 1)
>   End
> 
> each with argument 10e4 and 10e4 times, I get the following timings in
> milliseconds:
> 
>   3115
>   4246
> 
> Regards,
> Tobi
> 
> [1] https://gitlab.com/gambas/gambas/blob/master/main/gbx/gbx_exec_loop.c#L940
> [2] https://gitlab.com/gambas/gambas/blob/master/main/gbx/gbx_exec_loop.c#L1059
> 
> [*] For example, I took care not to have g allocate a new local variable
>     on each call, because f doesn't do that. Both do two additions per
>     "iteration" and have a single conditional.
> 
> -- 
> "There's an old saying: Don't change anything... ever!" -- Mr. Monk
> 
> ----[ Gambas mailing-list is hosted by https://www.hostsharing.net ]----
> 
> ----[ Gambas mailing-list is hosted by https://www.hostsharing.net ]----
------- End of Original Message -------



More information about the User mailing list