Declare as local, really needed?
BlitzMax Forums/BlitzMax Programming/Declare as local, really needed?
| ||
The title says it, i had a quick question on wheter it is or is not good to declare local variables. I did some tests, and the game runs as well with as without declarations. Globals, obviously do have function. |
| ||
Well, you have no option to not declare them. Code without strict / superstrict will suffer missing optimations etc. As well, your code will not be accepted as "clean" or really acceptable if you ever post it here ... as some of the issues come due to the fact that strict is not used. (its not there for fun. its mainly optional instead of enforced to have the converted Blitz3D / BlitzPlus code working as you can not use strict on those as they use int handles which are a big no no in BM performance wise) As well, local is very important to the GarbageCollector as the place where you define it defines where it becomes invalid and can be cleaned for sure. Variable scopes don't exist without strict, beside "function" and "application" |
| ||
It's good practice to have as many variables local as possible. That will give better code-reusability, and it's essential for blackboxing. In the true coders Utopia, there are barely any globals.. ^_^ |
| ||
Oh, thanks for the info! In that case ill strict my RPG now i still can :) When a variable is declared as local, do you recommend i also defint the TType? :Int, :String, :TBank, etc... ? And if i want to set a default value, how do i add this? for a TBank for example. Would that be =null or, could i just leave it like that? How would this effect the code? |
| ||
I recommend Superstrict, that'll teach ya, muhuhaha! |
| ||
BM default inits stuff. String = "", numerics = 0, types other than strings are = null And yes, set the type always ... and avoid the "numerics shortcuts" (ie %, # etc as well as $ for string) they are nice for lazyness ... but don't make the code that much better to read. |
| ||
haha, ok. i already felt the pain of Strict. When im done ill try Superstrict. In line of all this, i had another question. How important is it to open ( close ) paramaters when calling functions? I learned that you MUST use () if you want it to return. Otherwise you can leave it as well away. Any comments? |
| ||
Depends on your own style. I use them everywhere, just to make it visually clear that it is a function, not some kind of strange variable or the like. |
| ||
My goodness. I just finished the Strict. I GAINED +10FPS.... amazing! just amazing... I thoughd that the more code i added, the slower it would go. But by defining it all, it even gets waayyy faster. |
| ||
yupp because the GarbageCollector can flag them as dead and remove them far earlier ... for example a local defined within an IF will be cleaned when you reach else or endif of that IF |
| ||
cool. @CS_TBL hah. i now work with superstrict. its the best :P i kinda felt it was a bit messy to leave all intgers undefined, so i though, heck, why not? :P |
| ||
Local variables tell the compiler to try to use a CPU register to store a value rather than store it in memory. This makes a lot of sense if you are going to be accessing the same values many times or want to work with a relatively small number of variables often. If you are doing lots of bigger memory access or parts of your code are quite different and not re-used much then you might not see any benefit. I try to use as many locals as possible and I never think about the garbage collector (that's the point of it). If I a coding tighter loops or doing lots of calculations I particularly try to put values into locals and generally the code does run faster. I would definitely avoid making all your variables global. |
| ||
Locals still get stored in the memory, that being the stack. |
| ||
Strict and superstrict are the same apart from strict assumes any variables you have not specified the type of are int. Superstrict requires you to specifiy the type of all variables, even if they are int. The performance between the two is the same - the difference is only cosmetic. (If all but one type of variable are specified, the compiler can safely assume what an unspecified variable is). Not using strict the compiler can only guess what variable type you are using and because you do not need to declare the variables, it doesn't know where they belong. For example, a variable declared inside an if block using strict does not exist after the endif (try it, on strict) and allows the compiler to make all kinds of wonderful optimizations. For example registers are stored in super-quick memory inside the processor cache, but if the compiler doesn't know where each variable "belongs" it cannot smartly decide which belong in the registers. |
| ||
Superstrict should be the one and only default. You know, just as in Pascal. ;-) |
| ||
Superstrict should be the one and only default. Yep! :-) |
| ||
ohboy. so even storing local's inside a for/next loop is faster then outside? |
| ||
From a theoretical design point of view, you should make your variables accessable only where they are needed. If they are needed only in a particular section of code, then only that section of code should be allowed to access them. It just so happens this also tends to result in better and more bug-resistant code. If code that doesn't need the variable, can't get at the variable, then there's no chance it might screw up with the variable. I'm not too savy on any figures about whether it is faster or not, but from a design point of view, if the variables are only required *inside* the for loop, then declare it only inside the loop. The problem with that, though, is it will reset the variable each time the loop is ran, in which case you have no choice but to declare the variable just before the loop. In this example we go through some bank accounts and find out how much money they have in another currency if the exchange rate is "rate". You could just store the calculation directly into totalmoney but for point of simple example, let's not. Local totalmoney:Int = 0 For Local tempaccount:TAccount = EachIn accountlist Local convertedmoney:Int = tempaccount.money * rate totalmoney :+ convertedmoney Next The convertedmoney variable does not exist outside the loop and attempting to access it will make the compiler complain the variable doesn't exist (on strict mode at least!) Which is good, because it doesn't make sense for the convertedmoney variable to continue existing after the loop. Its job is done. Thus potential errors are removed, and possibly the loop will run faster. |
| ||
...if the variables are only required *inside* the for loop, then declare it only inside the loop. The problem with that, though, is it will reset the variable each time the loop is ran. try this, works fine:For Local x:Int = 0 To 10 Print x Next |
| ||
That's not what he meant! In your example, x is defined once when the loop is initiated. What he meant, was something like this...SuperStrict For Local x:Int=0 Until 10 Local y:Int y:+1 Print x+" "+y Next In this example y will always return 1 because it's reset to 0 before it gets 1 added to it with every iteration of the loop. |
| ||
true. |
| ||
I find declaring Local variables in FOR loops a massive slowdown. this might be due to CPU cache size or whatever technical reason, but if you are after speed, find a way to put the foor loop in a new scope and declare the vars it will use before entering. It may not be great but it is considerably faster. |
| ||
Yupp definitely ... the constant "reiniting" if local within loop is a considerable overkill. |
| ||
Thanks for mentioning!! |
| ||
You can 'isolate' a piece of code in a scope like this,Repeat Local heheoutside For ... Next Until True Not very elegant, but it should do it. |
| ||
enclosing with if true is simpler :) does the same as using { } without any keyword in C++ |
| ||
In this example y will always return 1 because it's reset to 0 before it gets 1 added to it with every iteration of the loop. Wouldn't using Global (which isn't really a Global in this case, but rather a static local) solve that: SuperStrict For Local x:Int=0 Until 10 Global y:Int y:+1 Print x+" "+y Next Y still exists only within the loop but increments as desired. |
| ||
Since this topic is still going on, may i add: How do i declare private fields and methods in an TType? |
| ||
You can't. There is no such thing in BlitzMax. |
| ||
was afraid so, ah well... its a minor thing. :) |
| ||
was afraid so, ah well... its a minor thing. :) Oh no.. that's the secret incantation to envoke the wrath of the OOP gods! |
| ||
Oh no.. that's the secret incantation to envoke the wrath of the OOP gods! I thought the secret incantation was #Label Goto Label :D |
| ||
Strict, SuperStrict -> goto disabled Labels can only be used as looplabels and then with Continue LoopLabel / Exit LoopLabel :D |
| ||
Got another point. When in a method or function, when i return a value. It automaticly stops there right? Or does it pass the return, and finished the method or function? |
| ||
return exits the function of method. It can also be used on functions or methods that doesn't return any value, to force a 'exit function' or 'exit method' operation |
| ||
Try this. Think about how it would work in the two possibilities.Strict For Local a = 0 To 13 Print a + " is it prime? " + isprime(a) Next End Function isprime:Int(number) If number < 2 Then Return False Local maxfactor = number/2 For Local factor = 2 To maxfactor If Not (number Mod factor) Then Return False Next Return True End Function |
| ||
As discussed here: http://www.blitzbasic.com/Community/posts.php?topic=56598#629234 Locals do end up in CPU registers where possible and Globals end up in main memory. Hence the speedup. |