Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations wOOdy-Soft on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Constants

Status
Not open for further replies.

CCLINT

Programmer
Feb 22, 2002
3,802
DE
I have gotten into a debate concerning the use of constants for numbers:

The question was raised: Which of the following:
1. is more/less efficient
2. how much more/less effiecient
3. and if more efficient, when should it be used, and not used?
4. Solid arguments for the pros and cons (no baseless answers please).

Global Const g0% = 0
Global Const g1% = 1

Dim myInteger as Integer

myInteger = 1

Or

myInteger = g1

If the second choice, then should this be done for all numbers used, or just the top 100/most used?

Say, the program uses 1000 zeros and the same number of ones.

(If the 2nd, then shouldn't I be replacing all (most used) numbers with the constants?)
----------------------------------------------------------
Please note:
The discussion is not concerning strings, but numbers.
The discussion is not concerning the use of constants to make the code easier to read (like a set value).
But just simple used numbers. Even to the use on a conditional branch, say, in an Select Case on the Index on a control array.


I have stated my views in the discussion, but as opposed to using constants for strings or fixed values, my arguments are not (Technically) solid enough to offer the needed validated facts.

 
CCLINT, Even though you are trying to scare people of with 'no baseless answers' - I'm going to try my luck anyway ;-)

As I understand it the VB compiler simply replaces the constant with the value when compiling. I which case there is no performance gain/loss by using constants.

So I looked (briefly) around the web to find some documentation to support this view - but couldn't find any - sorry. Sunaj
'The gap between theory and practice is not as wide in theory as it is in practice'
 
Theoretically, constants are more efficient but I've never tried putting together any kind of test program to determine a) how true this is or b) how much more efficient they are.
 
Conventionally, it is preferred to have contants. In a style of sense and readibility, assigning values which could be placed as constants (such as MAX_ITEM = 10) is more preferred. The number 10 is denoted as a 'magic number' and is not preferred to be assigned like a normal temporary variable.

Im not sure what kind of answer you are looking for but Im just writing whatever is on my mind now :)

 
strongm - what is the theory behind that constants should be more efficient? Do they point to the same memory block? Sunaj
'The gap between theory and practice is not as wide in theory as it is in practice'
 
>no baseless answers

I guess those were the wrong words.

I really just didn't only want to hear:

Yes, they are better.
Or
I don't think it is good.



Using constants are more efficient than using variables, (and, this isn't what I meant above - comparing variables with constants -what I mean is comparing hard coded values with constants).

For instance this:

Option explicit

Const str1$ ="TESTME"

Sub Test1()
Dim str2 as string

Str2 = Str1
End Sub

is much more efficient than doing this:

Public str1 as String
Sub Form_Load()
str1 ="TEST"
End Sub

Sub Test1()
Dim str2 as string

Str2 = Str1
End Sub

But this should be obvious because a constant is resolved when the program is compiled. The value is written directly into code. With variables, each time the program finds one, it needs to get the current value. So, if someone is assigng a value to a public/global variable once, just to have it available anywhere in the program, you're better off hard coding the value, or, for better visibilty in the case of non-string values, using a constant.

Another good thing about using constants is that you can declare all the constants that you want, but when the program is compiled, and the constant is not used anywhere, it gets removed from the compiled version.

Back to the question:
I believe it makes no difference between a hard coded value and a value assigned to a constant in terms of efficiency( speed and program size), and, whether one way or the other, the values will get written into the compiled code at the place where used, and, as for the constant, into the value that it was assigned. I just cannot find anything to back this up.




 
Am running some tests now - will get back with results as soon as I have some to report Good Luck
--------------
As a circle of light increases so does the circumference of darkness around it. - Albert Einstein
 
sunaj: Good question. And I guess that would boil it all down to a single answer, and the answer to the question.
I feel that for every use of a constant in code, means another hard coded value. In otherwords, using the same constant twice means 2 entirely different "values" being stored directly into the compiled code in to locations as opposed to a pointer to another location, just like when hard coding a value.
This is of course different than when using a variable.
If this is true, then there is no advantage in using constants as opposed to hard coded values - except for visibility when writing code (can be read better, and if say, a factor has a value of 10 and you use the number 10 at 100 locations in code to represent this factor, and then later changes in business rules cause the factor to change to 11.....with a constant you only need to change it in one place), but a completely different issue when just assigning a value to a variable, and the value never changes, and then using this variable somewhere in the program.
 
I would have thought that the only performance gain from not using constants would be in the compilation itself (as then no substitution would be required).
This then raises the question of how you compile. If you compile to native code obviously all reference to the constant will be changed to the value. However if you compile to pseudo code then the program is being interpreted, so how does VB handle constants when interpreting? I would assume they are treated as 'write once' variables and substituted each time they are encountered. If this is so then in older versions of VB there may have been an issue, but now if you compile to native code it shouldn't matter which way you use.
I may be completely wrong, but these are my thoughts on the subject.

Matt
 
I timed the following two routines and compared values. On a slow (Celeron 450) computer, I had to go to 100,000,000 loops to get enough elapsed time for a decent comparison. Both loops ran at roughly .75 seconds. After running both loops, I compared the total time required for each type of loop, and it varied from the constant method being 2-3 mSecs faster to 2-3 mSecs slower.

Heres how the Constants were set elsewhere in the module:
Global Const TEST_NUM1 = 5
Global Const TEST_NUM2 = 3
Global Const NUM_LOOPS = 100000000

' These two Do Loops were placed in a timing routine that timed each method.

lngLoop = 1
Do
intDummy = 5 + 3
lngLoop = lngLoop + 1
Loop While lngLoop < NUM_LOOPS

lngLoop = 1
Do
intDummy = TEST_NUM1 + TEST_NUM2
lngLoop = lngLoop + 1
Loop While lngLoop < NUM_LOOPS
 
Given the following test code - compiled executable (VB6-SP5), with all background tasks halted for the duration of the test

'----------------------------------------------------------------------------------------------------------

Dim fCur_Start As Currency
Dim fCur_End As Currency
Dim fCur_Freq As Currency

Dim fDbl_LoopOverHead As Double

Const C_ONE = 1
Const CX_ONE% = 1
Const C_TWO = 2000000
Const CX_TWO& = 2000000

Private Sub cmdTimeTest_Click()

Dim lInt_Int1 As Integer
Dim lInt_Int2 As Integer
Dim lInt_Int3 As Integer
Dim lLng_Lng1 As Long
Dim lLng_Lng2 As Long
Dim lLng_Lng3 As Long

lLng_RetVal = QueryPerformanceFrequency(fCur_Freq)
lLng_RetVal = QueryPerformanceCounter(fCur_Start)
lLng_RetVal = QueryPerformanceCounter(fCur_End)

fDbl_LoopOverHead = 0
For lInt_TestIdx = 1 To lInt_TestCount
lLng_RetVal = QueryPerformanceCounter(fCur_Start)
For lInt_LoopIdx = 1 To lInt_LoopCount ' 32,500 Times
Next lInt_LoopIdx
lLng_RetVal = QueryPerformanceCounter(fCur_End)
fDbl_LoopOverHead = fDbl_LoopOverHead + CDbl((fCur_End - fCur_Start) / fCur_Freq)
Next lInt_TestIdx
fDbl_LoopOverHead = fDbl_LoopOverHead / lInt_TestCount

For lInt_TestIdx = 1 To lInt_TestCount ' 32,500 Test Iterations
For lInt_OptIdx = 1 To lInt_OptCount ' 6 Options (3 Int, 3 Long)
Select Case lInt_OptIdx
Case 1
lLng_RetVal = QueryPerformanceCounter(fCur_Start)
For lInt_LoopIdx = 1 To lInt_LoopCount ' 32,500 Times
lInt_Int1 = 1 ' Repeated 9900 Times
Next lInt_LoopIdx
lLng_RetVal = QueryPerformanceCounter(fCur_End)
Case 2
lLng_RetVal = QueryPerformanceCounter(fCur_Start)
For lInt_LoopIdx = 1 To lInt_LoopCount
lInt_Int2 = C_ONE
Next lInt_LoopIdx
lLng_RetVal = QueryPerformanceCounter(fCur_End)
Case 3
lLng_RetVal = QueryPerformanceCounter(fCur_Start)
For lInt_LoopIdx = 1 To lInt_LoopCount
lInt_Int3 = CX_ONE%
Next lInt_LoopIdx
lLng_RetVal = QueryPerformanceCounter(fCur_End)
Case 4
lLng_RetVal = QueryPerformanceCounter(fCur_Start)
For lInt_LoopIdx = 1 To lInt_LoopCount
lLng_Lng1 = 200000
Next lInt_LoopIdx
lLng_RetVal = QueryPerformanceCounter(fCur_End)
Case 5
lLng_RetVal = QueryPerformanceCounter(fCur_Start)
For lInt_LoopIdx = 1 To lInt_LoopCount
lLng_Lng2 = C_TWO
Next lInt_LoopIdx
lLng_RetVal = QueryPerformanceCounter(fCur_End)
Case 6
lLng_RetVal = QueryPerformanceCounter(fCur_Start)
For lInt_LoopIdx = 1 To lInt_LoopCount
lLng_Lng3 = CX_TWO&
Next lInt_LoopIdx
lLng_RetVal = QueryPerformanceCounter(fCur_End)
End Select
Next lInt_OptIdx
Next lInt_TestIdx

'------------------------------------------------------------------------------------------


The following results were obtained. All six cases had an average execution time of either .98 or .99 microseconds. Since the effective resolution of the QPC on this machine is approximately 4 microseconds, I think that we can conclude that in 3 out 4 times, the 9900 assignment statements were executed in a reported 0 microseconds (inside the 4us resolution of the QPC), and the other 25% of the time, reported an exec time of 4us.

Therefore, I think its safe to say, that the difference, if any, between literals and symbolic constants (with or without type suffix) is so negligable as to be inconsequential.

Thus, any decisions as to whether to use or not use symbolic constants should not be based on performance. Good Luck
--------------
As a circle of light increases so does the circumference of darkness around it. - Albert Einstein
 
(Sorry, I forgot to turn off the italics above)

CajunCenturion: Super! I just also did some testing in using a constant 20,000 times inside a loop(100) vs. using raw numbers. And calling the proceedure several times. In speed I couldn't find a difference. But I did the teseting hastily. Interested to see what you come up with.

MatDavies: Another interesting view.

djsiders: Thanks for testing. What did you use to time it with? If I understand right, you found the constant was sometimes slower and sometimes faster?
Also, the other (bigger) problem/question that is needed is when the same constant is used and coded many times in the program, and not just once.
 
Let me re-word that:
>I just also did some testing in using a constant 20,000 times inside a loop(100)

I just also did some testing where line of code with the constant assigned to the variable variable was copied 20,000 times, 1000 times into 20 subs proceedures and the call to the 20 sub proceedures were placed in a loop of 100 iterations.

---------------------------------------------------
Good results CajunCenturion!

So, 3 tests need to be done:
-The one I did for a comparison of speed, where the constant is not in just one location or line of code, but used, not in a loop, thousands of times in thousands of lines of code, vs. using a literal(I may have done it too fast the first time).

-What would also be interesting the EXE sizes using 20,000 constants vs. 20,000 literals (although, common sense says there should not be a difference).

-The last test just out of curiosity would be doing the same comparison using variables only (just to let people know the advantages).
 
CajunCenturion: >Thus, any decisions as to whether to use or not use symbolic constants should not be based on performance.

that is, Versus literals.....

---------------------------------------------------
Again, for anyone else reading this, it is not efficient to use a variable (which has been assigned a fixed value) vs. to using a constant or literal, i.e. a certain year value, or when using a fixed number as in pi.

Public sngMyRate as Single

Sub Form_Load()
sngMyRate =&quot;.04&quot;
End Sub

Sub Test1()
Text2.Text = sngMyRate * Text1.Text
End Sub

Then it would be more efficient to do the math or assigning variables using literals or a constant.

'Public sngMyRate as Single
Public Const cMYRATE = 0.04

Sub Form_Load()
'sngMyRate =&quot;.04&quot;
End Sub

Sub Test1()
Text2.Text = cMYRATE * Text1.Text
End Sub

 

So, Using the constant vs literal in 20,000 different lines of code, looping 1000 times (for a total of 20 mil). Tests were done compiling in P code, Native code. And Under Native code, Optimized for speed, for size and None options were tested.

In all compile types above:
Difference between using constants and literals = 0
Difference in size = 0

----------------------------------------------------
Differences when compiled differently:

Size:

Native code
-&quot;Not optimised&quot; largest;
-&quot;Optimize for size&quot; was 20% smaller;
-&quot;Optimize for speed&quot; was also 20% smaller;

P-code
-33% smaller than Native code &quot;Optimised for size&quot;.


Speed:

Native code
-&quot;Optimize for speed&quot; was slowest!;
-&quot;Not optimised&quot; and &quot;Optimize for size&quot; were 2.9% faster;

P-code -Fastest
- 6.8% faster than Native code optimised for speed.


I still need to do the last comparison with values of variables assigned to other variables.


 
So if I understand what you are saying, The P-code version actually ran faster? I didn't expect that at all!

 
I used the QueryPerformanceCounter pretty much the same way Cajun did.
 


MatDavies: neither did I.......
Of course, we are only dealing here with a few factors.

djsiders: Right on.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top