Photo Gallery Member List Search Calendars FAQ Ticket List Log Out


Optimizing VBScript

 
Logged in as: Guest
arrSession:exec spGetSession 2,16,39632
 Active Users: There are 0 members and 0 guests.
 Users viewing this topic: none
 

 

 
  
  Printable Version
All Forums >> [Scripting] >> Post a VBScript >> Optimizing VBScript
  Do you like VisualBasicScript.com? Link to us and help spread the word about our forum. Thanks!
Page: [1]
Login
Message << Older Topic   Newer Topic >>
 Optimizing VBScript - 11/12/2006 7:22:09 AM   
  TNO


Posts: 1056
Score: 10
Joined: 12/18/2004
From: thenewobjective.com
Status: offline
VBScript and JScript can both be optimized for better execution speed and a lower overhead by followng some of the same tricks that other languages like Java and C++ follow. Heres a short guide on what you can do (referenced from a variety of internet sources and adapted/Translated by yours truly for VBScript). With smaller scripts these techniques are generally not required, but when you get to application level development with your scripts optimization become apparent.


#1 Minimize The DOM

In your HTA applications often times you have to manipulate the Document Object Model to access your page elements.
Interacting with the DOM is significantly more complicated than arithmetic computations, which makes it slower. When the Scripting interpreter encounters a scoped object, the engine resolves the reference by looking up the first object in the chain and working its way through the next object until it finds the referenced property. To maximize object resolution speed, minimize the scope chain of objects. Each node reference within an element's scope chain means more lookups for the browser. Keep in mind that there are exceptions, like the window object, which is faster to fully reference. So instead of this:


      

Do this


      

Object-oriented techniques encourage encapsulation by tacking sub-nodes and methods onto objects. However, object-property lookups are slow, especially if there is an evaluation. So instead of this:


      

Do This:

Dim e
e=a.b.c.d

For I = 1 To 1000
     e(I)
Next

Reduce the number of dots (object.property) and brackets (object["property"]) in your program by caching frequently used objects and properties. Nested properties are the worst offenders (object.property.property.property).

Also, accessing a named property or object requires a lookup. When possible, refer to the object or property directly by using an index into an object array. So instead of this:


      

Do This:


      

Scope Chains:

Every time a function executes, the script creates an execution context that defines its own little world for local variables. Each execution context has an associated scope chain object that defines the object's place in the document's hierarchy. The scope chain lists the objects within the global namespace that are searched when evaluating an object or property. Each time the script begins executing, certain built-in objects are created.
The global object lists the properties (global variables) and predefined values and functions (vbNewLine, vbArray, etc.) that are available to all VBScript programs.
Each time a function executes, a temporary call object is created. The function's arguments and variables are stored as properties of its call object. Local variables are properties of the call object. Within each call object is the calling scope. Each set of brackets or new Function recursively defines a new child of that scope. When the Script looks up a variable (called variable name resolution), the script interpreter looks first in the local scope (Like the current function), then in its parent, then in the parent of that scope, and so on until it hits the global scope. In other words, the script looks at the first item in the scope chain, and if it doesn't find the variable, it bubbles up the chain until it hits the global object. That's why global scopes are slow. They are worst-case scenarios for object lookups.
During execution, only With statements and catch clauses affect the scope chain.

The with statement extends the scope chain temporarily with a computed object, executes a statement with this longer scope chain, and then restores the original scope chain. This can save you typing time, but cost you execution time. Each additional child node you refer to means more work for the browser or HTA  in scanning the global namespace of your document. So instead of this:


      

Do this:


      

Cache the object or property reference instead of using With, and use this variable for repeated references. And if you're using JavaScript/JScript/ECMAScript, with also has been deprecated, so it is best avoided.

Dynamic Page Content:

Simply put generating page content from code is the slowest:


      

A little faster is to write the literal element:


      

And even faster is to write all the html before hand before writing it to the page. This is because every time you write to the page, the browser/HTA refreshes the display in order to show the element

By the same token, avoid multiple document.writes in favor of one document.write of a concatenated string. So instead of this:


      

Do this:


      

Access NodeLists Directly NodeLists are lists of elements from object properties like .childNodes and methods like getElementsByTagName(). Because these objects are live (updated immediately when the underlying document changes), they are memory intensive and can take up many CPU cycles. If you need a NodeList for only a moment, it is faster to index directly into the list. Browsers are optimized to access node lists this way. So instead of this:


      

Do this:


      



In most cases, this is faster than caching the NodeList. In the second example, the browser doesn't need to create the node list object. It needs only to find the element at index i at that exact moment.





#2 Local Optimizations:

Cache Frequently Used Values

One of the most effective techniques you can use to speed up your scripts is to cache frequently used values. When you cache frequently used expressions and objects, you do not need to recompute them. So instead of this:



      

Do this:




      
Store Precomputed Results For expensive functions (like Sin()), you can precompute values and store the results. You can use a lookup table (O(1)) to handle any subsequent function calls instead of recomputing the function (which is expensive). So instead of this:




      

Do this:


      

This technique is often used with trigonometric functions for animation purposes. A sine wave makes an excellent approximation of the acceleration and deceleration of a body in motion. In JScript and VBScript, this technique is less effective than it is in a compiled language like C. Unchanging values are computed at compile time in C, while in an interpreted language they are computed at runtime.

Comments and whitespace in your script:

You can comment and pad your code with whitespace as much as you like, all you are going to affect is the initial load and parse time which will effect you more if you are loading your script over the web or over a network vice locally. That is because the script interpreter removes whitespace and comments at runtime before it executes your script.

Name Length of Functions:

When it comes to Function names:  Function a() vs Function MyFunctionThatCalculatesTheWidthOfMyCircleHereInThisBracket(i)

Its pretty clear that in JScript/VBScript the length of the function name matters. In compiled languages, every function call is compiled down to a memory address. In interpreted systems the function name is important. So if you have lots of long and descriptive function names, you are probably taking a performance hit of a few percent, which makes for a hard decision or readability over ultimate performance. For me, 1% is worth it if my function names can be easy to read and bear some resemblance to the actions they perform.

Loop Speed:


Reverse Loops:

Reversing loop conditions so that they count down instead of up can double the speed of loops. Counting down to zero is faster than counting up to a number of iterations for some reason. So instead of this:


      

Do This:


      

Unroll or Eliminate Loops Unrolling a loop reduces the cost of loop overhead by decreasing the number of times you check the loop condition. Essentially, loop unrolling increases the number of computations per iteration. To unroll a loop, you perform two or more of the same statements for each iteration, and increment the counter accordingly. So instead of this:


      

Do This:

Dim iter, i
iter = multiple_of_number_of_unroll_statements


      

I've unrolled this loop six times, so the number of iterations must be a multiple of six. The effectiveness of loop unrolling depends on the number of operations per iteration. Again, the simpler, the better. For simple statements, loop unrolling in your script can speed inner loops by as much as 50 to 65 percent. But what if the number of iterations is not known beforehand? That's where techniques like Duff's Device come in handy.
Duff's DeviceInvented by programmer Tom Duff while he was at Lucasfilm Ltd. in 1983, Duff's Device generalizes the loop unrolling process. Using this technique, you can unroll loops to your heart's content without knowing the number of iterations beforehand. The original algorithm combined a do-while and a switch statement. The technique combines loop unrolling, loop reversal, and loop flipping. So instead of this:


      

Do This:

quote:

Function duffLoop(iterations)
Dim testVal
testVal=0
'Begin actual Duff's Device
'Original VBS Implementation by TNO as far as I know
Dim n
n = iterations / 8
Dim caseTest
caseTest= iterations Mod 8

Do
    Select Case caseTest
        Case 0 [modify testVal here]
        Case 7 [ditto]
        Case 6 [ditto]
        Case 5 [ditto]
        Case 4 [ditto]
        Case 3 [ditto]
        Case 2 [ditto]
        Case 1 [ditto]
    End Select
    caseTest=0;
Loop While n-1 > 0
End Function


Like a normal unrolled loop, the number of loop iterations (n = iterations/8) is a multiple of the degree of unrolling (8, in this example). Unlike a normal unrolled loop, the modulus (caseTest = iterations % 8) handles the remainder of any leftover iterations through the switch/case logic. This technique is 8 to 44 percent faster in IE5+.
Fast Duff's Device You can avoid the complex do/switch logic by unrolling Duff's Device into two loops. So instead of the original, do this:


      


The effect diminishes as the degree of loop unrolling increases. Even after two statements, the time to loop through many iterations is less than 50 percent of a normal for loop. Around seven statements, the time is cut by two-thirds. Anything over eight reaches a point of diminishing returns. Depending on your requirements, I recommend that you choose to unroll critical loops by between four and eight statements for Duff's Device.


Fuse Loops


If you have two loops in close proximity that use the same number of iterations (and don't affect each other), you can combine them into one loop. So instead of this:



      



Do this:


      


Fusing loops avoids the additional overhead of another loop control structure and is more compact.

Expression Tuning As regular expression connoisseurs can attest, tuning expressions themselves can speed up things considerably. Count the number of operations within critical loops and try to reduce their number and strength. If the evaluation of an expression is costly, replace it with a less-expensive operation. Assuming that a is greater than 0, instead of this:


      



Do This:


      

Or even better:



      

Strength reduction is the process of simplifying expensive operations like multiplication, division, and modulus into cheap operations like addition, OR, AND, and shifting. Loop conditions and statements should be as simple as possible to minimize loop overhead.So instead of this:


      

Do This:


      

This technique simplifies the test condition from an inequality to a decrement, which also doubles as an exit condition once it reaches zero

Summary To speed execution, optimize your code at the right design level or combination of levels. Start with global optimizations first (for example, algorithm and data structure choices), and then move down toward more local optimizations until your program is fast enough. Refactor to simplify your code, and then minimize DOM interaction and I/O requests. Finally, if all else fails, tune your code locally in some of the ways mentioned.

If you have any suggestions, corrections and so on, please feel free to post. We can all learn from each other on this subject

< Message edited by TNO -- 11/17/2006 11:54:08 PM >


_____________________________

Consolidated Script Component: The Acid Test

A universe of complexity...
 
 
Revisions: 2 | Post #: 1
 
 RE: Optimizing VBScript - 11/17/2006 1:19:38 PM   
  Fredledingue


Posts: 333
Score: 0
Joined: 5/9/2005
From:
Status: offline
That's the most surprising!

      

but why "To  i>0" ?

I always use "To 0" (or whatever number).
And it whould be faster.

-------

next tip:

Avoid conditions (if, or, and) in loops
I notice that by far, it's the number of conditions that define the lenght of a loop.

------

Dim 'ing the variable sometimes increase the speed. But not always.







_____________________________

Fred

(in reply to TNO)
 
 
Post #: 2
 
 RE: Optimizing VBScript - 11/17/2006 4:44:44 PM   
  TNO


Posts: 1056
Score: 10
Joined: 12/18/2004
From: thenewobjective.com
Status: offline
quote:

but why "To  i>0" ?


Actually you're 100% correct. I wasn't paying attention to the loops as I was translating them from JS:


      

I'm correcting them now.

_____________________________

Consolidated Script Component: The Acid Test

A universe of complexity...

(in reply to Fredledingue)
 
 
Post #: 3
 
 RE: Optimizing VBScript - 11/17/2006 10:29:22 PM   
  Fredledingue


Posts: 333
Score: 0
Joined: 5/9/2005
From:
Status: offline
Loop While (i=i-1)
 
doesn't need brackets:

Loop While i=i-1

_____________________________

Fred

(in reply to TNO)
 
 
Post #: 4
 
 RE: Optimizing VBScript - 11/17/2006 11:54:58 PM   
  TNO


Posts: 1056
Score: 10
Joined: 12/18/2004
From: thenewobjective.com
Status: offline


_____________________________

Consolidated Script Component: The Acid Test

A universe of complexity...

(in reply to Fredledingue)
 
 
Post #: 5
 
 RE: Optimizing VBScript - 11/28/2006 3:10:02 PM   
  kirrilian


Posts: 628
Score: 3
Joined: 3/15/2005
From:
Status: offline
I have to admit I'm surprised about the reverse loops myself, I'll have to give that a go on some of my slower/bigger scripts and see if i can lean them up a bit

thanks!



_____________________________

Have you searched here ?
VBScript Fundamentals
My Site

(in reply to TNO)
 
 
Post #: 6
 
 
 
  

If you found our site useful please link to us <a href="http://www.visualbasicscript.com">VisualBasicScript.com</a>.
All Forums >> [Scripting] >> Post a VBScript >> Optimizing VBScript Page: [1]
Jump to:





New Messages No New Messages
Hot Topic w/ New Messages Hot Topic w/o New Messages
Locked w/ New Messages Locked w/o New Messages
 Post New Thread
 Reply to Message
 Post New Poll
 Submit Vote
 Delete My Own Post
 Delete My Own Thread
 Rate Posts