Results 1 to 18 of 18

Thread: GOSUB - Is It Realy That Bad?

  1. #1

    Thread Starter
    Hyperactive Member
    Join Date
    Feb 2015
    Location
    Colorado USA
    Posts
    261

    GOSUB - Is It Realy That Bad?

    I posted this earlier today in the VB6 section but for those of you who don't read those threads I htought I would repeat it here...

    I like GOSUB. I started programming in Assembly and Turbo Pascal back when PC's first came out in the early ‘80s so I have been doing this for a long time.

    There are two main advantages of using GOSUB: 1) no variables to push/pop from the stack and 2) any local variables don't need to initialized and destroyed on each call.

    The supposed disadvantages of using GOSUB are: 1) it just isn't modern coding practice, 2) it leads to spaghetti code that is very hard to use and maintain, 3) it is only like a Sub and it can’t return a value like a Function and 4) because of (1) and (2) most younger programmers don’t even know when/how to use it and most “modern” programming languages don’t even include it.

    Processors use gosub internally. They also use a lot of what is the equivalent of the GOTO command in VB/VBA but that is a discussion for another day.

    I also find that GOSUB doesn’t make me write spaghetti code (at least any more than I do without using it). I can find a line label in my current procedure as fast as I can find a standalone routine and with proper commenting I dno’t hae any additional code maintenance issues.

    I keep reading statements by other programmers about their disdain for GOSUB but their arguments are weak to non-existent for why we shouldn’t use it and why it made sense for Microsoft to remove it from VB.NET. I think that’s crazy so I decided I would test my assumptions regarding speed.

    I worked up something approximating a real-world scenario and I wrote a simple program that call the repeating code via a Function and I wrote another routine that called the repeating code via a GOSUB command.

    I got some very surprising results. Below are the time in milliseconds to execute the code 10,000 times.

    Using Function Using GOSUB
    VBA 1,092 475
    Un-compiled VB6 960 472
    Compiled VB6 371 866
    Compiled VB6 (p-code) 906 435


    The code in VBA did about what I thought it would. This is basically like pseudo-code that can be “compiled” by VB6; it is not native machine code. The GOSUB code is 2.3 times faster.

    Un-compiled VB6 is similar to VBA; the function calls are about 13% faster but the GOSUB code is only marginally faster than VBA although it is 2 times faster than the Function call code.

    Using VB6 with code compiled to p-code was similar to un-compiled VB6 code but about 5-8% faster. I don’t use p-code for a variety of reasons but it is a bit faster than either VBA or un-compiled VB6. However, note that the GOSUB version is a bit more than 2 times faster like the other codings.

    The surprise comes with code compiled to native machine code. BTW, the results were very similar when I optimized for small code or faster execution. As expected the use of the Function code was a bit over twice as fast. What was surprising was that the code using GOSUB was over 2.3 times as slow as the Function version and twice as slow as all of the other versions of the GOSUB coding for VBA, un-compiled VB6 and p-code VB6. Whoever did the compiler logic for GOSUB in VB6 did a horrible job!

    So the bottom-line for me is that GOSUB is the way to go for VBA but programs using compiled VB6 to machine code will run faster with conventional Function or Sub calls.

    I have the code and raw results available if anyone wants to play with them.

  2. #2
    Member
    Join Date
    May 2021
    Posts
    40

    Re: GOSUB - Is It Realy That Bad?

    Hi,MountainMan
    I have a classic basic code for my mechanical design, it contains many gosub lines. I dont want to translate it to VB6's sub function or sub routine. So would you show me an example how to use gosub in VB6? Thanks.

    John

  3. #3
    Smooth Moperator techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,531

    Re: GOSUB - Is It Realy That Bad?

    Yeah GOSUB goes way back in time doesn't it? The execution speed doesn't surprise me... you can GOSUB to a label, which means you can't pass parameters. With a method you can, so there's some overhead in calling one as things have to be pushed to the stack first. With a gosub, it's just (or should be) a JMP to a specific memory address.

    I'd be curious to see your testing code for this...The compiled VB6 numbers I find a bit surprising, especially considering the others.

    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  4. #4
    PowerPoster yereverluvinuncleber's Avatar
    Join Date
    Feb 2014
    Location
    Norfolk UK (inbred)
    Posts
    2,235

    Re: GOSUB - Is It Realy That Bad?

    You forgot, you cannot define local scope and encapsulate variables using gosubs ...
    https://github.com/yereverluvinunclebert

    Skillset: VMS,DOS,Windows Sysadmin from 1985, fault-tolerance, VaxCluster, Alpha,Sparc. DCL,QB,VBDOS- VB6,.NET, PHP,NODE.JS, Graphic Design, Project Manager, CMS, Quad Electronics. classic cars & m'bikes. Artist in water & oils. Historian.

    By the power invested in me, all the threads I start are battle free zones - no arguing about the benefits of VB6 over .NET here please. Happiness must reign.

  5. #5
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,647

    Re: GOSUB - Is It Realy That Bad?

    The compiled speed should put the final nail in the coffin. That plus the downsides, it's not worth it for a benefit in the IDE.

    VBA has enough problems with unreadable and unmaintainable code. Half a second for 10,000 executions isn't worth it. If anything is that performance critical, it should have already been outsourced to a native DLL (which is a lot more practical now that tB can do it for x64 VBA in the same language).

    There's also no comparison against an even better solution of redesigning to not need either GoSub or another function.

  6. #6
    Member
    Join Date
    Apr 2019
    Posts
    63

    Re: GOSUB - Is It Realy That Bad?

    Hi MountainMan

    Would be worth posting the code. Benchmarks without code aren't great because you can never tell if the implementor had an alterior motive, not saying you do

    I must say I'm not a fan of GOSUB, mostly because you can't post parameters to the GOSUB block, and scope becomes hugely polluted. In a similar fashion, I'm also not a fan of having a tonne of global variables. I do enjoy seperating concerns.

    One "interesting" feature of GOSUB though is that you don't lose scope. This means you can iterate over IEnumVariants in a different part of your code.

    Code:
    Public Function ForEach(Optional ByVal cb As stdICallable, Optional ByVal WithIndex as boolean = false) As stdEnumerator
        Dim bLoopInitialised as boolean: bLoopInitialised = false
        Dim ExitLoop as Boolean: ExitLoop = false
        Dim v as variant, i as long: i=0
        Do while true
            'Increment index
            i=i+1
    
            'Obtain loop var from mode
            select case mode
                case EnumeratorType.FromCallable
                    if bLoopInitialised then
                        v = pCallback.run(v,i)
                    else
                        v = pCallback.Run(null,i)
                        bLoopInitialised=true
                    end if
                    if isNull(v) then ExitLoop = true
                case EnumeratorType.FromIEnumVariant
                    if bLoopInitialised then
                        GoSub NextItem
                    else
                        GoSub InitIEnumVARIANT
                        bLoopInitialised = True
                    end if
                case EnumeratorType.FromIEnumVariant
                    if bLoopInitialised then
                        if lb+i-1 <= ub then
                            v = vArr(lb+i-1)
                        else
                            ExitLoop = true
                        end if
                    else
                        Dim lb as long: lb = lbound(vArr,1)
                        Dim ub as long: ub = ubound(vArr,1)
                        if ub-lb+1 > 0 then
                            v = vArr(lb+i-1)
                        else
                            v = null
                        end if
                    end if
            end select
            if ExitLoop then Exit Do
    
            if withIndex then
                Call cb.Run(i,v)
            else
                Call cb.Run(v)
            end if
        Loop
    
        set ForEach = me
        Exit Function
    
    '=========================================================================================================================
    ' IEnumVARIANT Iterator - Don't change the code below
    '=================================
    InitIEnumVARIANT:
        For Each v In pEnumObject
            Return
    NextItem:
        Next
        ExitLoop = true
        Return
    End Function
    Of course there are better ways to do this though. I wouldn't suggest anyone ever use code like this, as it really is confusing af...

    I'm on a similar wavelength to fafalone here. Even though I use VBA regularly, VBA has enough problems with unreadable or unmaintainable code. Encouraging bad practice for such a minor performance gain, is it worth it?

  7. #7
    PowerPoster PlausiblyDamp's Avatar
    Join Date
    Dec 2016
    Location
    Pontypool, Wales
    Posts
    2,458

    Re: GOSUB - Is It Realy That Bad?

    Quote Originally Posted by MountainMan View Post
    So the bottom-line for me is that GOSUB is the way to go for VBA but programs using compiled VB6 to machine code will run faster with conventional Function or Sub calls.

    I have the code and raw results available if anyone wants to play with them.
    I am not sure how your conclusion was to use GOSUB from those benchmarks... GOSUB would result in a lot of global variables, harder to read (and therefore maintain) code, and the performance difference is about 500ms for 10,000 iterations (that is approx 0.05ms difference per call).

    I am not convinced the performance boost for most situations would justify the code quality issues that would arise, under certain performance critical sections then it might possible be justified. Although if I wanted to write performance critical code I wouldn't be doing it in VBA anyway

  8. #8
    Member
    Join Date
    Apr 2019
    Posts
    63

    Re: GOSUB - Is It Realy That Bad?

    Quote Originally Posted by PlausiblyDamp View Post
    Although if I wanted to write performance critical code I wouldn't be doing it in VBA anyway
    To be fair, it isn't always a choice.

  9. #9
    PowerPoster yereverluvinuncleber's Avatar
    Join Date
    Feb 2014
    Location
    Norfolk UK (inbred)
    Posts
    2,235

    Re: GOSUB - Is It Realy That Bad?

    I used to code serious applications in DCL, a scripting language for VMS systems. I created demonstration RAD applications in pseudo code, converting to intermediate DCL to form working templates for eventual conversion to fortran, these programs would assist factory production at Mars chocolate, scheduled chocolate levels vs actual & c. Due to limitations of this language I had to use GOSUBs instead of sub routines/functions and I am telling you now how easy it is to remove/lose the matching return, it happens!. RETURNS are not physically paired to a GOSUB, any return you hit sends you back... not necessarily when you want it to. It is NOT a recommended method for really obvious control reasons regardless as to whether it is performant in speed.
    https://github.com/yereverluvinunclebert

    Skillset: VMS,DOS,Windows Sysadmin from 1985, fault-tolerance, VaxCluster, Alpha,Sparc. DCL,QB,VBDOS- VB6,.NET, PHP,NODE.JS, Graphic Design, Project Manager, CMS, Quad Electronics. classic cars & m'bikes. Artist in water & oils. Historian.

    By the power invested in me, all the threads I start are battle free zones - no arguing about the benefits of VB6 over .NET here please. Happiness must reign.

  10. #10

    Thread Starter
    Hyperactive Member
    Join Date
    Feb 2015
    Location
    Colorado USA
    Posts
    261

    Re: GOSUB - Is It Realy That Bad?

    Quote Originally Posted by PlausiblyDamp View Post
    I am not sure how your conclusion was to use GOSUB from those benchmarks... GOSUB would result in a lot of global variables,...
    PlausiblyDamp,

    A Gosub has to be in the same procedure as the calling code so it has access to all of the variables already in that procedure. So it doesn't cause any increase in Global variables. In fact, if you use say 10 parameters you had defined in the parent procedure, you would almost certainly have to pass them as parameters for a separate procedure call whereas in a Gosub they are already defined and likely have their values that don't need to be passed on the stack to a Gosub..

  11. #11

    Thread Starter
    Hyperactive Member
    Join Date
    Feb 2015
    Location
    Colorado USA
    Posts
    261

    Re: GOSUB - Is It Realy That Bad?

    Quote Originally Posted by fafalone View Post
    The compiled speed should put the final nail in the coffin. That plus the downsides, it's not worth it for a benefit in the IDE.

    VBA has enough problems with unreadable and unmaintainable code. Half a second for 10,000 executions isn't worth it. If anything is that performance critical, it should have already been outsourced to a native DLL (which is a lot more practical now that tB can do it for x64 VBA in the same language).
    Strange, you use the performance times to say that Gosub has no advantage outside of the IDE but then say the difference in performance time means you shouldn't use Gosub. I am not sure you can have it both ways.

    I disagree that VBA code is unreadable and unmaintainable. I've been doing VB/VBA for a long time and I don't find the VBA code to be worse than VB6. It does have the Win64 conditional compilation constant that makes things look goofy but this a) enabled us to use VBA in 64-bit Excel and b) TB is going to put us in the same situation on Windows 64-bit coding. Also, if TB ca n generate native DLL's when it is released doesn't exclude use of those DLL's in VBA.

  12. #12

    Thread Starter
    Hyperactive Member
    Join Date
    Feb 2015
    Location
    Colorado USA
    Posts
    261

    Re: GOSUB - Is It Realy That Bad?

    Quote Originally Posted by yereverluvinuncleber View Post
    You forgot, you cannot define local scope and encapsulate variables using gosubs ...
    I am not sure I understand your concern about local scope. Since Gosub's have to be embedded within a Procedure they have access to any procedure-level vari9abes and the global variables just like the code elsewhere calling the Gosub. In fact, if you Dim a variable in a Gosub that variable will go out of scope when the parent procedure goes out of scope.

  13. #13
    PowerPoster PlausiblyDamp's Avatar
    Join Date
    Dec 2016
    Location
    Pontypool, Wales
    Posts
    2,458

    Re: GOSUB - Is It Realy That Bad?

    Quote Originally Posted by MountainMan View Post
    PlausiblyDamp,

    A Gosub has to be in the same procedure as the calling code so it has access to all of the variables already in that procedure. So it doesn't cause any increase in Global variables. In fact, if you use say 10 parameters you had defined in the parent procedure, you would almost certainly have to pass them as parameters for a separate procedure call whereas in a Gosub they are already defined and likely have their values that don't need to be passed on the stack to a Gosub..
    Point taken, although if you have a procedure with a lot of variables declared and are using Gosub a lot then the procedure level variables are almost acting like global variables anyway. I am a big fan of simpler, smaller functions, locally declared variables, and functions with minimal side effects - Gosub pretty much goes against all of these things though.

  14. #14

    Thread Starter
    Hyperactive Member
    Join Date
    Feb 2015
    Location
    Colorado USA
    Posts
    261

    Re: GOSUB - Is It Realy That Bad?

    Quote Originally Posted by techgnome View Post
    Yeah GOSUB goes way back in time doesn't it? The execution speed doesn't surprise me... you can GOSUB to a label, which means you can't pass parameters. With a method you can, so there's some overhead in calling one as things have to be pushed to the stack first. With a gosub, it's just (or should be) a JMP to a specific memory address.

    I'd be curious to see your testing code for this...The compiled VB6 numbers I find a bit surprising, especially considering the others.

    -tg
    Techgnome, I will post code for VB6 and VBA (it is almost identical code) in the next day or so.

    I disagree with not being able to pass variables. You just have to think about it a bit differently. It's true that the return address is the only thing put on the stack (so Return sends it back to the right place) but any variable you have in the calling procedure is available to the Gosub code. So if I have a variable "i" and I want to pass it to a Sub or a Function, I have to put it on the stack as a parameter in the call. With a Gosub, you have immediate access to "i". It is the same as passing a variable to a Proc "ByRef". If you want to have it be the equivalent of "ByVal" then you just use some other variable of the same type in your procedure (or you Di it in the Gosub; it only gets allocated once). That's basically how the VB compiler works anyway. When you do ByVal the compiler makes a copy of the variable on the stack, doing essentially exactly what I described.

  15. #15

    Thread Starter
    Hyperactive Member
    Join Date
    Feb 2015
    Location
    Colorado USA
    Posts
    261

    Re: GOSUB - Is It Realy That Bad?

    Quote Originally Posted by JT870 View Post
    Hi,MountainMan
    I have a classic basic code for my mechanical design, it contains many gosub lines. I dont want to translate it to VB6's sub function or sub routine. So would you show me an example how to use gosub in VB6? Thanks.

    John
    John, it is incredibly easy to use. I am going to post my latest code in a day or so so you should be able to see how easy it is.

  16. #16

    Thread Starter
    Hyperactive Member
    Join Date
    Feb 2015
    Location
    Colorado USA
    Posts
    261

    Re: GOSUB - Is It Realy That Bad?

    [QUOTE=JT870 Hi,MountainMan
    I have a classic basic code for my mechanical design, it contains many gosub lines. I dont want to translate it to VB6's sub function or sub routine. So would you show me an example how to use gosub in VB6? Thanks.[/QUOTE]

    John,

    Below is a very simple example of a Gosub in VB6/VBA. Note that what the subroutine does in this example is trivial and I would never write code using a Gosub like this but it should be simple and easy-to-understand.

    Sub GosubExample()
    Dim x As Long, y As Long, z As Long
    x = 5
    y = 6
    GoSub MyGosubStart 'should put 11 in z
    MsgBox z
    Exit Sub


    MyGosubStart:
    z = x + y ' procedure-level variables x & y Dim'd and values set above in the procedure
    Return
    End Sub

  17. #17
    PowerPoster
    Join Date
    Nov 2017
    Posts
    3,116

    Re: GOSUB - Is It Realy That Bad?

    Yes, it can be bad. This is some code (very slightly modified) from the "Chaos and Fractals" book printed in the early 1990's. Pretty much all the code in each chapter has Gosub and Goto jumps that made it really hard to track down issues where the code I entered manually wasn't producing results identical to the book pictures.

    Code:
    ' Filename:  CANTORST.BAS
    ' Comments:  This program draws the Cantor set staircase.
    
    CLS
    
    DIM xleft(10) AS DOUBLE
    DIM yleft(10) AS DOUBLE
    DIM xright(10) AS DOUBLE
    DIM yright(10) AS DOUBLE
    DIM r AS DOUBLE
    DIM level AS INTEGER
    DIM stair AS DOUBLE
    DIM left AS INTEGER
    DIM w AS INTEGER
    
    INPUT "Part to remove (0 - 1): ", r
    level = 7
    stair = 1
    left = 30
    w = 420
    
    xleft(level) = left
    xright(level) = left + w
    yleft(level) = left + .5 * (1 + stair) * w
    yright(level) = left + .5 * (1 - stair) * w
    
    SCREEN 12
    
    ' Compute dimension
    IF r < 1 THEN d = LOG(2) / LOG(2 / (1 - r)) ELSE d = 0
    PRINT "Dimension of Cantor set", d
    GOSUB 100
    END
    
    
    ' Draw line at lowest level of recursion
    100 :
      IF level > 1 GOTO 200
      LINE (xleft(1), yleft(1))-(xright(1), yright(1))
      GOTO 300
    
    ' Branch into lower levels
    200 :
      level = level - 1
    
      ' Left branch
      xleft(level) = xleft(level + 1)
      yleft(level) = yleft(level + 1)
      xright(level) = .5 * ((1 - r) * xright(level + 1) + (1 + r) * xleft(level + 1))
      yright(level) = .5 * (yright(level + 1) + yleft(level + 1))
      GOSUB 100
    
      ' Right branch
      xleft(level) = .5 * ((1 + r) * xright(level + 1) + (1 - r) * xleft(level + 1))
      yleft(level) = .5 * (yright(level + 1) + yleft(level + 1))
      IF stair THEN LINE (xleft(level), yleft(level))-(xright(level), yright(level))
      xright(level) = xright(level + 1)
      yright(level) = yright(level + 1)
      GOSUB 100
    
      level = level + 1
    
    300 :
      RETURN

  18. #18
    PowerPoster PlausiblyDamp's Avatar
    Join Date
    Dec 2016
    Location
    Pontypool, Wales
    Posts
    2,458

    Re: GOSUB - Is It Realy That Bad?

    Quote Originally Posted by MountainMan View Post
    John,

    Below is a very simple example of a Gosub in VB6/VBA. Note that what the subroutine does in this example is trivial and I would never write code using a Gosub like this but it should be simple and easy-to-understand.

    Sub GosubExample()
    Dim x As Long, y As Long, z As Long
    x = 5
    y = 6
    GoSub MyGosubStart 'should put 11 in z
    MsgBox z
    Exit Sub


    MyGosubStart:
    z = x + y ' procedure-level variables x & y Dim'd and values set above in the procedure
    Return
    End Sub
    One of the problems with that style of code is you have no idea what variables need to be set, or are modified, by the code after the Gosub without going and reading that code. With a function it would be obvious that you pass in two Longs and it returns a long. Also using a gosub means those three variables have very specific uses that isn't immediately obvious - if you gosub to that section then z will be overwritten.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width