I have a small procedure that is being run VERY often (@5Hz) and it currently resides in a module outside of the form that calls it. Would it be faster if I moved it into the code of the form?
Printable View
I have a small procedure that is being run VERY often (@5Hz) and it currently resides in a module outside of the form that calls it. Would it be faster if I moved it into the code of the form?
Yes, procedure calls take time. Any parameters need to be passed/copied, and the code flow needs to jump (and jump back again afterwards).
I once improved the speed of some code using this method, it went from doing 200 iterations per second to over 2000. (results will vary depending on the code involved).
Obviously it may mean having to write the same code in more than one place, but if you are after speed it is an appropriate thing to do.
A call is a call is a call. Doesn't matter where it is (unless it's in a separate object such as a dll or some such). If it's in a code module in the same project, moving it isn't going to help. Maybe what you should do is take a second look at it and see if there is a way to optimize it to run better.
TG
T.G. is right - I meant to say that you should put the code inline (ie: dont have it as a procedure)... browser crashed mid post tho :(
There are many ways of optimising code, but it all depends on what you are doing, and how you are doing it. If you post the code (and an explanation of what it needs to do) we can give better advice.
Putting procedures inline does give a speed boost, but it may be more hassle than it is worth, as you can easily get un-readble and hard-to-maintain code.
Here is the code:It is checking to see if the time for a step in the program has expired. I have a timer on my main form that is set to 200ms that calls it. It seems to be working ok so far, but I still have a lot of functionality to build into the system (limit checking, data logging, value display, etc) and I want to make sure this runs as clean as possible.VB Code:
Public Sub GetStepTime() Dim lngTemp As Long On Error GoTo GetStepTime_Error If NEWSTEP Then STARTSTEPTIME = GetTickCount lngTemp = frmMain.flxSP2.CellText(STEPNUM, 4) FULLSTEPTIME = lngTemp * 1000 NEWSTEP = False Else CURSTEPTIME = GetTickCount If CURSTEPTIME - STARTSTEPTIME > FULLSTEPTIME Then NEWSTEP = True STEPNUM = STEPNUM + 1 End If End If On Error GoTo 0 Exit Sub GetStepTime_Error: LogError Err.Number, Err.Description, Err.Source, False, "GetStepTime of Module basDurb" End Sub
One thing that I was going to do to try and optomize it is to put the times into an array so that I'm not reading the value from a control on every pass.
Timer controls are not very good - apparently they are only accurate to about 70ms (that's up to 35% out with 200ms). They also have various other 'issues', as detailed in many posts on this forum.
An API timer would be a far more accurate method (if you are concerned with a specific frequency, this can only be a good thing).
You are right that reading from a control is slow, what is the reason for having it? (I don't understand from what you have already posted).
If you really want to optimize for speed, replace 1000, 4 and 1 with constants.
BTW, you also don't need the On error Goto 0 line.
Can you recommend a good API timer? Should I use the SetTimer API? The only reason I was reading the value from a control is that I was going to let the user change the step time while running the test.... however, this is not necessary and would be far from the norm, so I guess reading it from an array would work just as easily.Quote:
Originally posted by si_the_geek
An API timer would be a far more accurate method (if you are concerned with a specific frequency, this can only be a good thing).
You are right that reading from a control is slow, what is the reason for having it? (I don't understand from what you have already posted).
Martin, I will change those to constants, thank you.
Ok, another question... each "step" I have been referring to has 4 parts and I'll have to refer to each part when the step is changes, so I might as well load them all into arrays..... so would it be faster to have a UDT of arrays, a 2 dimensional array, or 4 seperate arrays? The 4th part of each step will be hammered on much more than the other parts.
In other words, I'll be checking the 4th element to see if that much time has passed, and then I'll be loading the other 3 parts for the next step when that time has expired.
Is this making sense?
Martin,
I was not aware that "literal" values in VB were not compiled into constants in the .EXE. Are you saying that having the value 1 in a math equation is slower than using a constant that is assigned to the value 1?
Why?
^ What he said. That would seem idiotic if it's the case.
I would also like elaboration on this topic.
All I can do is to quote from MSDN which says under the Optimizing for Speed topic
Maybe it's really talking about variables but I don't know.Quote:
Use Constants Whenever Possible
Using constants makes your application run faster. Constants also make your code more readable and easier to maintain. If there are strings or numbers in your code that don’t change, declare them as constants. Constants are resolved once when your program is compiled, with the appropriate value written into the code. With variables, however, each time the application runs and finds a variable, it needs to get the current value of the variable.
Whenever possible, use the intrinsic constants listed in the Object Browser rather than creating your own. You don’t need to worry about including modules that contain unused constants in your application; when you make an .exe file, unused constants are removed.
I think it means don't do something like:
VB Code:
Dim bla as long bla = 5 Dim i as long Dim total as long for i = 0 to 10 total = total + bla next
Clearly "bla" is unecessary and that code might cause more fetches from memory. It's a bit of a no-brainer though.
I just found that substituting a constant for a number is faster. Here is the code that I ran as an exe.
On my PC the code using FIVE took 16 ms while the code using 5 took 31 ms.VB Code:
Dim lngStart As Long Dim lngFinish As Long Dim lngCounterOne As Long Dim lngCounterTwo As Long Const FIVE As Integer = 5 ' Record the start "time" lngStart = GetTickCount() ' Some process that you want to time For lngCounterOne = 1 To 9000000 lngCounterTwo = lngCounterTwo + FIVE Next lngCounterOne ' Record the finish "time" lngFinish = GetTickCount() ' Display the difference MsgBox CStr(lngFinish - lngStart) lngStart = GetTickCount() ' Some process that you want to time For lngCounterOne = 1 To 9000000 lngCounterTwo = lngCounterTwo + 5 Next lngCounterOne ' Record the finish "time" lngFinish = GetTickCount() ' Display the difference MsgBox CStr(lngFinish - lngStart)
That's pretty strange, it looks like VB does behave like you said. Try more iterations though - GTC's resolution is only ~30ms.
When I change 9000000 to 90000000 I get 187 vs 203.
CStopWatch Class by Karl Moore
This is an excellent class you can add to your project and call - great example to show you how to use it....
QueryPeformanceCounter is better ;) But that aside, I tested the code on my PC and I'm seeing the opposite - the "5" code runs consistently faster.
MartinLiss: to get more accurate results, please make two different projects and EXEs. I've seen VB giving weird results when you run two test after each other in one code. As separate I've got much more accurate results.
Update: using QueryPerformanceCounter and seprarating out the two tests, I'm seeing no difference in performance between the pieces of code. This is with 900000000 iterations and averaging over 10 runs.
Yup, was as I thought: two tests in the same EXE is unreliable. Maybe this can be skipped in one project by making the tests behind separate command buttons. Thought it'd be plain silly if you had to use declared constants instead of constant numbers.
Yeh I put the tests in two functions behind two command buttons. It's not completely ideal, because the test you run first always runs about ~2ms slower, probably because of caching, but the whichever you run first, it's always the case, so the performance is identical.