MiBol
MiBol

Reputation: 2125

VB.NET How give best performance "Select case" or IF... ELSEIF ... ELSE... END IF

I have a huge DataTable, and I need go by each row and validate an specific value.

Which method give me more performance, an structure of IF ELSE or SELECT CASE? (I'm focused in the method that offer me the best performance)

IF ELSE (METHOD #1)

For Each vRow In vDTtemp.Rows
    If vRow("Item") = "Time" Then
        vRow("Result") = "000"
    ElseIf vRow("Item") = "DateTime" Then
        vRow("Result") = "001"
    ElseIf vRow("Item") = "String" Then
        vRow("Result") = "002"
    Else
        vRow("Result") = "N/A"
    End If
Next

SELECT CASE (METHOD #2)

For Each vRow In vDTtemp.Rows
    Select Case vRow("Item")
        Case "Time"
            vRow("Result") = "000"
        Case "DateTime"
            vRow("Result") = "001"
        Case "String"
            vRow("Result") = "002"
        Case Else
            vRow("Result") = "N/A"
    End Select
Next

Upvotes: 6

Views: 26507

Answers (4)

Ivan Font
Ivan Font

Reputation: 73

Ok... it was long time ago for this post, but now i was searching the same question and i can add new optimization for this. For now i've choosed to use the select case, for be more readable. In the other hand, the performance decreases a lot when a "Dim" is inside a for-next loop.

     For Each vRow In vDTtemp.Rows
------->  Dim rowItem = vRow("Item")
        If rowItem = "Time" Then
            vRow("Result") = "000"
        ElseIf rowItem = "DateTime" Then
            vRow("Result") = "001"
        ElseIf rowItem = "String" Then
            vRow("Result") = "002"
        Else
            vRow("Result") = "N/A"
        End If
    Next

It's a lot faster when dim is oitside even if you want to use the if-then structure:

------->     Dim rowItem as string
             For Each vRow In vDTtemp.Rows
------->            rowitem= vRow("Item")
                If rowItem = "Time" Then
                    vRow("Result") = "000"
                ElseIf rowItem = "DateTime" Then
                    vRow("Result") = "001"
                ElseIf rowItem = "String" Then
                    vRow("Result") = "002"
                Else
                    vRow("Result") = "N/A"
                End If
            Next

I hope this be helpful for someone more ;)

Upvotes: 5

Adam Dawes
Adam Dawes

Reputation: 198

I've spent quite a lot of time working on this same problem over the last couple of days and have found one approach which is much faster than the others. I too found that using Select Case on a string variable was equivalent to a series of If/Else If statements, and both were disappointingly slow.

However the following technique has worked very well, and reduced the amount of time by over 50%. Instead of the original code:

For Each vRow In vDTtemp.Rows
    Select Case vRow("Item")
        Case "Time"
            vRow("Result") = "000"
        Case "DateTime"
            vRow("Result") = "001"
        Case "String"
            vRow("Result") = "002"
        Case Else
            vRow("Result") = "N/A"
    End Select
Next

Change it around to switch on a simple Boolean, and use the String.Equals method, like this:

For Each vRow In vDTtemp.Rows
    'Read out the row value so we only need to access the datarow once
    rowValue = vRow("Item")
    'Which of these statements is true?
    Select Case True
        Case rowValue.Equals("Time")
            vRow("Result") = "000"
        Case rowValue.Equals("DateTime")
            vRow("Result") = "001"
        Case rowValue.Equals("String")
            vRow("Result") = "002"
        Case Else
            vRow("Result") = "N/A"
    End Select
Next

I've had significant improvements by approaching it in this way, in one case reducing my code from 1.3 seconds over a 100,000 iteration loop to 0.5 seconds. If this is in a really frequently-called time-critical section of code, that can make a big difference.

As pointed out in the comments below however, this performs an "Ordinal" comparison of strings, which may not result in the expected behaviour if non-English locales are being used (see the comments for examples).

Adam.

Upvotes: 5

Hans Passant
Hans Passant

Reputation: 941635

It makes no difference, both code styles generate the exact same IL. Something you can see by running the ildasm.exe tool on your compiled assembly.

In general, the VB.NET compiler does make an effort to optimize a Select statement. That will work when it uses a simple value type as the selector and trivial Case statements. The generated code will use a dedicated IL instruction, Opcodes.Switch. Which will be compiled to machine code that uses a lookup table. Very fast.

That however doesn't work when you use a string expression as the selector. Making a lookup table for that one would require the equivalent of a dictionary of delegates. That's too impactful, the compiler cannot do anything but convert each case statement to the equivalent of an If statement. You can however optimize it yourself easily by creating this Dictionary in your code, easy to do since the dictionary key and value are just simple strings. You don't have enough cases and the strings are too short to make this pay off majorly, although it is worth a try. It certainly can compact your code.

Upvotes: 6

Jim Wooley
Jim Wooley

Reputation: 10398

If you really find this is your bottleneck in performance, you could try modifying the If..Then clause as follows to only access the indexer once:

For Each vRow In vDTtemp.Rows
    Dim rowItem = vRow("Item")
    If rowItem = "Time" Then
        vRow("Result") = "000"
    ElseIf rowItem = "DateTime" Then
        vRow("Result") = "001"
    ElseIf rowItem = "String" Then
        vRow("Result") = "002"
    Else
        vRow("Result") = "N/A"
    End If
Next

That being said, I suspect each of these is a case of over optimizing. The compiler should to the best thing here. If you check the IL from a long Select Case, you may find that it uses a string of If..then clauses under the covers with "goto" to escape the rest of the clauses. Your best option here is to get the most maintainable code as the performance benefits you may gain will be offset by the minimal boost you may see between if..then and select case.

Upvotes: 2

Related Questions