GOSUB instead PROCEDURE barrier ?

Everything else that doesn't fall into one of the other PB categories.
Ralf
Enthusiast
Enthusiast
Posts: 203
Joined: Fri May 30, 2003 1:29 pm
Location: Germany

GOSUB instead PROCEDURE barrier ?

Post by Ralf »

i am working on a program with a lot of procedures. this would looks like:

Code: Select all

Procedure Test1(val1,val2,val3...)
    ...Code1A - Never the same code...  
    ...Code1B - ThisPart is ever the same...
EndProcedure

Procedure Test2(val1,val2,val3...)
    ...Code2A - Never the same code...  
    ...Code2B - ThisPart is ever the same...
EndProcedure

Procedure Test3(val1,val2,val3...)
    ...Code3A - Never the same code...  
    ...Code3B - ThisPart is ever the same...
EndProcedure
As you may see, the CodeB part is in nearly every procedure and this part is ever exactly the same :!:

So i thought about a subroutine to store only the CodeB part and call this subroutine with GOSUB inside a procedure, like:

Code: Select all

Procedure Test1(val1,val2,val3...)
    ...Code1A - Never the same code...  
    Gosub SubRoutine
EndProcedure

Procedure Test2(val1,val2,val3...)
    ...Code2A - Never the same code...  
    Gosub SubRoutine
EndProcedure

Procedure Test3(val1,val2,val3...)
    ...Code3A - Never the same code...  
    Gosub SubRoutine
EndProcedure

SubRoutine:
    ...CodeB
Return
I know i have to set the variables from the procedures as global to use it in a subroutine too!? But the way to call a subroutine inside a procedure does not works! :evil:

So i thought and stored the subroutine code into a new procedure, which works! But this way is very bad for my code, because when calling the main procedure and this is calling a such called sub-procedure, my program runs about factor 100 slower ;( (here an example of the way, that slow down my program)

Code: Select all

Procedure SubRoutine(val1,val2,val3...)
    ...CodeB  
EndProcedure
;---------------------------------------------------
Procedure Test1(val1,val2,val3...)
    ...Code1A - Never the same code...  
    SubRoutine(val1,val2,val3...)
EndProcedure

Procedure Test1(val1,val2,val3...)
    ...Code1A - Never the same code...  
    SubRoutine(val1,val2,val3...)
EndProcedure
Is there really no other way like GOSUB, without loosing so much performance? Ok, i could copy the full subroutine (CodeB) and paste it into each Procedure! There are good and bad reasons for this way...

Code: Select all

good reasons would be:
-------------------------------------------------------------
* no performance loose
* small exe filesize

bad reasons would be:
-------------------------------------------------------------
* if you will change or modify anything of the CodeB part, you have not
to change this only onces! You have to change this all there, where you use the same code...  (still silly, even if you only want to change one value and have 50 procedures for example)

* filesize of the exe will be bloody big (instead having the routine only once in the whole program)
maybe someone can see my problem and have a solution for this problem! Btw, are Gosubs in C/C++/C# or any other languages inside a procedure of function forbidden too? fred?
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Post by Rescator »

You could turn CodeB into it's own procedure,
and call that from all the other CodeA procedures.
That way you write the code only once,
and no need for global vars, you just pass on the vars in the procedure args.

And if the CodeB procedure need to edit/change the vars of the CodeA vars,
simply pass the args using a reference @
Ralf
Enthusiast
Enthusiast
Posts: 203
Joined: Fri May 30, 2003 1:29 pm
Location: Germany

Post by Ralf »

Rescator wrote:You could turn CodeB into it's own procedure,
and call that from all the other CodeA procedures.
That way you write the code only once,
and no need for global vars, you just pass on the vars in the procedure args.

And if the CodeB procedure need to edit/change the vars of the CodeA vars,
simply pass the args using a reference @
That is exactly what i tried, like my third codesnip i posted! this will slow down the program by factor 100 ;/ (or do you mean i should do something with @ ?
dell_jockey
Enthusiast
Enthusiast
Posts: 767
Joined: Sat Jan 24, 2004 6:56 pm

Post by dell_jockey »

this dilemma is a good reason for wanting a preprocessor. Write a macro once and have it inlined in all of your routines automatically by the preprocessor. Only feasible of course when this doesn't inflate the size of your application too much.
cheers,
dell_jockey
________
http://blog.forex-trading-ideas.com
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Post by Rescator »

Hmm. I have no clue what code you are making but...

What if you just made one big procedure.

And used labels and gotos/gosubs, inside the procedure?
That way you would not have to use globals,
and it certainaly would be faster than using a secondary procedure.

(you'll just be jumping around inside the procedure itself instead)

so

Procedure blah()
Check what code should be used then...
Code 1 here
Jump to B code
Code 2 here
Jump to B code
Code 3 here
Jump to B code

B code here
EndProcedure

Actually the Code3 don't have to jump as B code follows right after.

Obviously you need a quick check at the very start,
and again depending on the code you make,
you may use jumps to go to the Code1 and Code2 etc.
Or just If Elseif etc. which may be simpler as you'll avoid using too many lables and jumps/gotos :)

In fact, depending on your code.
using just if and elsif
you could just put the B code after endif.
and no need for any jumps.
Ralf
Enthusiast
Enthusiast
Posts: 203
Joined: Fri May 30, 2003 1:29 pm
Location: Germany

Post by Ralf »

@ dell_jockey:
yes, you are right! macros would help here a bit but it doesnt really solve the problem to have a small exe file! (i still think its stupid to have one routine x times in a program instead only one time you can jump to. isnt it?)
Rescator wrote:Hmm. I have no clue what code you are making but...

What if you just made one big procedure.

And used labels and gotos/gosubs, inside the procedure?
That way you would not have to use globals,
and it certainaly would be faster than using a secondary procedure.

(you'll just be jumping around inside the procedure itself instead)

so

Procedure blah()
Check what code should be used then...
Code 1 here
Jump to B code
Code 2 here
Jump to B code
Code 3 here
Jump to B code

B code here
EndProcedure

Actually the Code3 don't have to jump as B code follows right after.

Obviously you need a quick check at the very start,
and again depending on the code you make,
you may use jumps to go to the Code1 and Code2 etc.
Or just If Elseif etc. which may be simpler as you'll avoid using too many lables and jumps/gotos :)

In fact, depending on your code.
using just if and elsif
you could just put the B code after endif.
and no need for any jumps.
Mhhh i think i know what you mean! The only problem each procedure have different amount of arguments (from 2 up to 12 arguments atm)
But one argument is in each procedure the same! And this is the part wher e i need the big CodeB stuff!

So your idea to have just only one procedure and include all other procedures as labels would be nice but not possible in this example ;(

I really need something like:

Code: Select all

Procedure Test1(val1,val2,val3...)
    ...CodeA <- Never the same code... 
    Gosub SubRoutine <- in each procedure the same code
EndProcedure

SubRoutine:
    ...CodeB
Return 
But jumping with GOSUB outside of a procedure isnt possible in pure (other languages the same :?: )

I would live with following idea - to call a procedure inside a procedure - but it really eats to much time (about 100 times slower) :evil:

Isnt there any way to call another Procedure inside a Procedure that works much faster? What about * or @ !?? Never used this before, is there any possibility?
Tension
User
User
Posts: 29
Joined: Tue Mar 22, 2005 3:19 pm

Post by Tension »

Ralf,

Perhaps CallFunctionFast would give some improvement of speed, something like:

Code: Select all

Procedure myB( .... )
 ..
EndProcedure

global myBaddr

myBaddr=@myB()

Procedure myFuncA( .. )
  ..
  CallFunctionFast(myBaddr, ...)
EndProcedure

etc
Forgive typos - also check the manual as I just typed this in without any checks myself.
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Post by Rescator »

Question.

How many variables and values does CodeB use/change from the CodeA stuff?

And does anything happen after CodeB is done?

EDIT: Hmm, Tension. Isn't that exactly the same as normally using a procedure? I'm not sure (ask Fred) but I believe that once compiled a PB program actually uses CallFast internally :P
Tension
User
User
Posts: 29
Joined: Tue Mar 22, 2005 3:19 pm

Post by Tension »

Rescator wrote:Hmm, Tension. Isn't that exactly the same as normally using a procedure? I'm not sure (ask Fred) but I believe that once compiled a PB program actually uses CallFast internally :P
You could be right.

Worth a shot though. Then at least Ralf will have the satisfaction of knowing he tried everything he could - and at worst, he got in some extra typing practice. :)
dell_jockey
Enthusiast
Enthusiast
Posts: 767
Joined: Sat Jan 24, 2004 6:56 pm

Post by dell_jockey »

Ralf,

Rescators question is indeed a good one. In case you have more than a couple of variables that are passed on with every function call, you might want to consider storing these variables in a structure. That way, you only have to pass on a single pointer to that structure. This is bound to be faster.
cheers,
dell_jockey
________
http://blog.forex-trading-ideas.com
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Post by Rescator »

Personally this is how I would have done it:
(without knowing what the heck your code is though, heh :P

Code: Select all

Procedure Test(val1,val2,val3)

 condition=2 ;check and set the conditional operation here
             ;you could possibly set the condition as 
             ;a procedure argument along with the val's above too.

 Select condition ;do the appropriate A code
  Case 1
   Debug "code1 stuff here"
  Case 2
   Debug "code2 stuff here"
  Case 3
   Debug "code3 stuff here"
 EndSelect

 ;B code stuff here
 Debug "Weeee, zoom zoom"

EndProcedure

; Let's test it :)

Test(0,0,0)
The entire procedure may get quite big eventually,
esp. if you have a lot of A code/conditions.

But at least you only write each code once,
thus making a much smaller program.
And most importantly, very fast indeed.

I'm not sure how fast PB's Select statement is,
but it is a pretty fast way to do conditional code.
alternatively one could use if, elseif/else, endif.

And if using select or similar isn't fast enough...
Well, you might wanna consider assembler if you want it any faster :P

Another bonus my using the Select method is that you do not have to copy or pass around pointers or values between procedures.
(this is why as you say, the procedure method slows down things so much.)
And even by using Goto and then another Goto to "get back"
you would still have the issue of variables having to be global and whatnot.

So try the Select method first and see how that works out,
you should if anything find it fast, and you save coding time
(and gain speed) by letting both A code and B code use the same variables etc.

You loose a little in code readability when you start getting a gigantic procedure, but there is really no way around it unless slower code is a option.
Last edited by Rescator on Sat Mar 26, 2005 3:32 pm, edited 2 times in total.
Ralf
Enthusiast
Enthusiast
Posts: 203
Joined: Fri May 30, 2003 1:29 pm
Location: Germany

Post by Ralf »

Rescator wrote:Question.

How many variables and values does CodeB use/change from the CodeA stuff?

And does anything happen after CodeB is done?


Ok, i will try to explain... Each procedure have a different amount of agruments as i said before. One of this arguements is named 'lColor' and is available as argument in each procedure!

Inside each procedure i split 'lColor' (= procedure agrument) into 'lRed', 'lGreen' and 'lBlue' variables (i can set this variables as global if necessarily!! So i have splitted the 24 bit RGB color value into 0-255 values for each color for easier handling!!

This and some more stuff stuff is available in CodeA part! Then it will still continue with CodeB (the second part)!

When i put all the CodeB stuff into a new procedure (because this part is needed as second part in every procedure!), following will happen:

To execute the CodeB part, i need the lRed, lGreen, lBlue and 4 more variables (all created inside CodeA, also no arguments from the first Procedure (CodeA) !!! Also all in one there are 8 variables i must share from CodeA to CodeB !!!

Hope i havent explained it to cryptish!? many thanks!
dell_jockey
Enthusiast
Enthusiast
Posts: 767
Joined: Sat Jan 24, 2004 6:56 pm

Post by dell_jockey »

are you doing cubic spline interpolation on each of the three color planes?
cheers,
dell_jockey
________
http://blog.forex-trading-ideas.com
Tension
User
User
Posts: 29
Joined: Tue Mar 22, 2005 3:19 pm

Post by Tension »

Rescator wrote:I'm not sure how fast PB's Select statement is,
but it is a pretty fast way to do conditional code.
alternatively one could use if, elseif/else, endif.
Last time I checked this (pre 3.93) If .. elseif outperformed select. But it was some time and some updates ago.

The idea of using structures is good. And the idea of doing conditional checks inside one proc does seem to be the best solution given that speed is an issue.
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Post by Rescator »

Ah. Still confusing but...

You can use the same Test() procedure.


Just make sure that the first set of variables matches if possible.

If not then don't worry. PB suppot "at least" 17 variables passed on procedure call time.

And you can simply do.


Test(0,0,0,0,0,0,0,255,246,126)

Since Code2 for example don't use the first variables but only the later ones, all the others are just ignored simply.

So combine this with my example above and you should get what you want.
Post Reply