Tuesday, May 22, 2007

VB.NET - CType & DirectCast

I was just wondering why .Net provides two type conversion functionalities for us even though both are casting to targeted type. But now I could understand that they are different.

  1. CTypeCType is more flexible than DirectCast. Because CType can convert one type to another. For example Integer to String, String to Integer, Object to Integer etc... But there should be an implicit conversion available. For example,

    Dim a As String = "2"
    Dim b As Integer
    b=a

    This will work if the Option Strict is OFF. Because implicit casting functionality for converting string to integer is available in .Net. That's why we can use CType to cast from string to integer .

    Example:

    Dim t As String = "5"
    Dim s As Integer = CType(t, Integer)

    Now I would like to tell working of CType. CType will use vb run time routines for this. So this happens at run time. For instance i have to convert an integer to string. .Net will create a reference type variable for string. Then it will copy that integer to the new instance of string. Then it will return that string.
    Here .Net uses run time resources. The integer is a value type. So Boxing is needed for converting to reference type(String). This will hit efficiency.
  2. DirectCastExample:


    Dim t As String = "5"
    Dim w As Integer = DirectCast(t, Integer) This will not work

    But,


    Dim t As String = "5"
    Dim w As String = DirectCast(t, String)

    This will work. That means the type of source variable should be same as casting type at run time.
    One more example:


    Dim t As Object
    t = 5
    Dim w As Integer = DirectCast(t, Integer) This will work. But the following will not work. It will throw System.InvalidCastException

    Dim t As Object
    t = "5"
    Dim w As Integer = DirectCast(t, Integer)

    So we should know the type of the object at coding time.

    DirectCast is faster than CType, because this is not using runtime VB helper functions. And there is no boxing, because DirectCast accepts only reference types as operands.
  3. Is DirectCast more efficient than CType?Yes.

    ---- DirectCast is not using run time helper functions for conversion.
    ---- No boxing in DirectCast
    ---- So DirectCast is two times faster than CType.

    But, there is a problem. The programmer need to ensure the run time type of the operand before using the DirectCast. If type may not match .Net will through Invalid cast exception. This is a big problem.

Friday, May 4, 2007

How Do We Speed Up Our VB.Net Web Applications

  1. Use Return statement to return value from functions
    The compiler can produce better code in some cases if you use the new Return statement to return a value from a function, instead of assigning the value to the variable named after the function itself (as you did in VB6).
  2. When comparing strings in a case-insensitive way, try using String.CompareOrdinal instead of the String.Compare method or the = and <> operators.
    The Compare method compares strings in a local-aware fashion, so it has to convert the Unicode code of each character into a numeric value that reflects its position in the current culture's alphabet. For example, the Compare method considers the "b" lowercase character to come immediately after the "A" uppercase char and before the "B" uppercase char, even though the "A" and "B" characters are contiguous in the Unicode character set. This conversion activity takes time and consume CPU cycles, so you'll find that VB.NET is less efficient than VB6 at comparing strings. Using the = operator and other comparison operators doesn't help at all, because they map to the Compare method behind the scenes, so these operators suffer from the same performance loss.

    If you are only interested in checking whether two strings contain the same characters (in a case-sensitive comparison), you can speed up your code by using the CompareOrdinal shared method. This method is 3-4 times faster than the Compare method (or the = operator) because it just scans the two strings and compare the Unicode numeric code of each character.
  3. StringBuilder is faster than & and +
    Try this

    dim Var1
    Var1= "This "
    Var1= Var1& "is old "
    Var1= Var1& "string "
    Var1= Var1& "concatenation."


    four variables are actually created. One on each line, and then memory is reallocated for the overlying variable which is created. Poor memory management.


    If you perform your string concatenation in the same way:

    Dim someString As New String()
    someString &= "This "
    someString &= "is old "
    someString &= "string "
    someString &= "concatenation."


    you still suffer the same performance degradation.

    However, we have been provided with a new class in .NET called the stringBuilder. And it dynamically allocates the memory block to the same object (the stringBuilder, itself, not the string)... expanding it on each concat so that you gain better performance. It resides in the system.text namespace and here's how you use it:

    Imports System.Text

    Dim newStringBuilder As New StringBuilder()
    newStringBuilder.Append("This ")
    newStringBuilder.Append("is new ")
    newStringBuilder.Append("string ")
    newStringBuilder.Append("concatenation.")

    Dim myString As New String(newStringBuilder.toString())


    So that they're really two separate objects, and the string builder takes care of memory management while you're building the string, and then you just call the .toString() method of the stringBuilder to output the result to the new string object, thereby only calling the new string() once, and avoiding the pitfalls of its inefficiencies.
  4. Speed up searches and replace string operations by using regular expressions. For example, this code displays all the individual words in a sentence:
    ' This code requires the following imports
    ' Imports System.Text.RegularExpressions

    Dim s As String = "Hi there, how are you?"
    Dim re As New Regex("\w+")
    Dim m As Match
    For Each m In re.Matches(s)
    Console.WriteLine(m.Value)
    Next
  5. Move as much code as possible outside of loops
  6. Use Loop Unrolling if possible Loop unrolling can eliminate some compare and jump instructions. (Compare and jump instructions are used to create loops, you don't see them in visual basic, its behind the scenes stuff that you learn in ASM.) It also takes advantage of the ability of modern cpus that can fetch several instructions at a time. In a nutshell you get a good speed boast by unrolling loops. But there is something we need to know about loop unrolling. The largest bottleneck on modern computers is memory. So the designers of CPU's like Intel and AMD addressed this problem by using a cache on their cpus. This is basically a memory location that is accessed much faster by the CPU then standard memory. You want your unrolled loop to fit in that cache, if it doesn't then it could slow down your code. So you may want to experiment with gettickcount when you unroll you're loop. Example Loop:
    Code:
    For i = 1 To 100
    b = somefun(b)
    Next i
    unrolled Example:
    Code:
    For i = 1 To 100 step 2
    b = somefun(b)
    b = somefun(b)
    Next i
  7. Avoid dividing if possible. A divide instruction is one of the most if not the most expensive instruction you can perform on a CPU. It is faster to multiply then divide!
    Code:
    B = 19 / 2
    is slower then
    Code:
    b = 19 * 0.5
  8. In a nested conditional branch such as select case and nested if statements, put the things that are most likely to be true first in the nest, with the least likely things last.
  9. Reduce common expressions. Sometimes you have two different variables that use part of the same calculation. Instead of doing the entire calculation for both variables, eliminate the redundant calculation.Example:
    Code:
    x = a * b + c
    y = a * b + d
    is slower then
    Code:
    t = a * b
    x = t + c
    y = t + d
    That is especially true if your using a redundant expensive calculation in a loop.
  10. Use long or integer for calculations. A long is a 32 bit number and is more natural on 32 bit processors. Avoid other variables such as double, single, etc
  11. Use inline functions inside of loops. Instead of calling a function, stick the code in the loop. This will make you're program larger if you repeat it in enough loops and should only be done in critical places. The reason is due to the over head of calling a function. Before the program calls a function, it has to push some things onto the stack. At the very least it will push the instruction pointer (IE: Return Address). Memory access is slow so we want to avoid that in critical places.
  12. Avoid using properties in loops. Properties are accessed a lot slower then variables, so use variables instead:
    Code:
    for i = 1 to 50
    text1.text = text1.text + b(i)
    next i
    is slower then
    Code:
    for i = 1 to 50
    strbuffer = strbuffer + b(i)
    next i
    text1.text = strbuffer. This is applicable to user defined properties also.
  13. Load all the data you need from the disk. Instead of loading one file at a time, load all of them at once. This will avoid future delay for the user.
  14. Make good use of the timer control. You can do background processing while waiting on a user. Use this time to prefetch data, calculations that are need, etc.
  15. Minimize dot notation in your objects Each dot you use in a object makes visual basic do a call.
    Code:
    Myobject.one.two.three
    is slower then
    Code:
    Myobject.one
  16. Allocate enough memory at once.
    When you create a dynamic array and you want to add elements that haven't been allocated yet, make sure you allocate enough for all of them instead of doing it one at a time. If you don't know how many you need, times what you have allocated by 2. Allocating memory is a expensive process
  17. Avoid built in functions in loops. If you have a algorithm that is looped that requires the len of your string. Make sure you cache the size of your string in a buffer and not call the function len() with each iteration of the loop:
    Code:
    for i = 1 to 100
    sz = len(string)
    'Do processing
    next i
    instead
    Code:
    sz = len(string)
    for i = 1 to 100
    'Do Processing with sz
    next i

  18. Dim x as integer,a as integer
    x=listbox.count-1
    for a= 0 to x
    next a
    This code id faster than

    Dim a as integer
    for a= 0 to listbox.count-1
    next a
    because the value would have to be calculated for each iteration of the loop in the second instance, which takes time.
  19. Reduce number of database access
  20. Do not rely on exceptions in your code. Since exceptions cause performance to suffer significantly, you should never use them as a way to control normal program flow. If it is possible to detect in code a condition that would cause an exception, do so. Do not catch the exception itself before you handle that condition. Common scenarios include checking for null, assigning a value to a String that will be parsed into a numeric value, or checking for specific values before applying math operations.
  21. Use the common language runtime's garbage collector and automatic memory management appropriately. Be careful about allocating too much memory per request because the garbage collector will have to do more work more often. Also, do not have unnecessary pointers to objects, since they will keep the objects alive, and try to avoid having objects with Finalize methods, since they will entail more work at a later time. In particular, never free resources in a call to Finalize, since the resource could consume memory until the garbage collector runs it. This last problem often ruins performance in Web server environments, since it can be easy to exhaust the availability of a given resource while waiting for Finalize to run.
  22. Use the HttpServerUtility.Transfer method to redirect between pages in the same application. Using this method in a page, with Server.Transfer syntax, avoids unnecessary client-side redirection.
  23. Use SQL Server stored procedures for data access.
    Of all the data access methods provided by the .NET Framework, SQL Server–based data access is the recommended choice for building high-performance, scalable Web applications. When using the managed SQL Server provider, you can get an additional performance boost by using compiled stored procedures instead of ad hoc queries.
  24. To navigate to a URL without posting the form, use a HyperLink control; to post the form and then navigate, use a LinkButton। To the Web page visitor, a HyperLink control and a LinkButton control look identical. However, there is a significant difference in functionality.The HyperLink control immediately navigates to the target URL when the user clicks on the control. The form is not posted to the server.The LinkButton control first posts the form to the server, then navigates to the URL. If you need to do any server-side processing before going to the target URL, use a LinkButton. On the other hand, if there is no server-side processing necessary, don't waste a round trip and use the HyperLink control.
  25. Keep Option Strict and Option Explicit on By keeping Option Strict and Option Explicit On there is a performance advantage. Option Explicit On forces explicit declaration of variable. If there is no explicit declaration compiler generates code for boxing. So the value types variables move to heap as reference type. This will hit performance.
    The Option Strict On forces explicit type casting. The implicit type casting will result late binding. This is very expensive. By keeping option strict on the programmer has to use explicit casting and this will result early binding. But, for backward compatibility VB.NET keeps Option Strict Off as default. Make sure Option Strict and Explicit on before coding.
  26. Avoid excessive round trips to server by providing client-side scripting Most of things like input validations can move to client-side from server-side. Most applications typical use of server side is for data storing and retrieving. So move the code that can do in client side. Then we can avoid excessive round trips to server
  27. Use Page.IsPostback to avoid extra work Some works like controls initializations, data fetch etc are requires performing only once. Avoid this by using Page.IsPostbak
  28. Disable Session State when not in use Not all applications or pages require per-user session state. If it is not required, disable it completely. This is easily accomplished using a page-level directive, such as the following: EnableSessionState="false" in page directive.
landscape paintings nature art landscape art sky art illustration art artwork art human art beautiful art landscape prints nature prints sky prints illustration prints artwork prints human prints beautiful prints beautiful special promotions nature special promotions sky special promotions illustration special promotions artwork special promotions beautiful canvas prints beautiful painting canvas prints beautiful framed prints beautiful painting framed prints beautiful posters beautiful painting posters