improve the exception handling vb.net

2019-03-06 21:32发布

问题:

I have a small trouble with the performance of the exception handling. I'm building... aaaaa... soooo...hmmm...a graph db? yeah something like this... with vb.net. I'm building the parser, for handling the basic functions of the db(?) What happen? The user makes a research, the program tab them, and allow to make some computation . Normally string handling, but, to give a complete instrument, I implement also mathematical functions.
There is no way to know developing-time math kind of value he is going to insert. And especially, there is no way to know if each row of the column that comes out the traversal has the same data type. It is a schema-free db(?). So what happen...I have to implement the error handling.

   For i As Integer = 0 To pR.r.wsRowCount - 1
                    Try
                        pR.r.wsItem(cix, i) = Convert.ToDouble(pR.r.wsItem(ca.ix, i)) * Convert.ToDouble(pR.r.wsItem(cb.ix, i))
                    Catch
                        pR.r.wsItem(cix, i) = String.Empty
                    End Try


                Next

Something like this... (psss.. Convert.toDouble() is the most performant function between cDbl(), Double.Parse() etc). But when I run it, if all the rows (benchmark around 2000 rows), are really numeric... few milliseconds, but if some rows are not numeric, it require 3 or 4 seconds. And worst scenario, if the user should do a mathematical operation in a string column... goodbye, meanwhile is better go to take a coffee. So my computer may be is not the most advanced in the world, but are you aware if there is any way to avoid this incredible delay in the error handling? I would remember that this is the parser of a query and I would avoid to make it heavy.

回答1:

You are using Exceptions to fix a problem when your code encounter a value that cannot be converted to a double. This is called driving your code using exceptions and it is a bad practice. Catching exceptions is never a good fix for this scenario.

In particular when there is a clear way to avoid them

 For i As Integer = 0 To pR.r.wsRowCount - 1
     Dim d1 As Double
     Dim d2 As Double

     if Double.TryParse(pR.r.wsItem(ca.ix, i), d1) Then
        if Double.TryParse(pR.r.wsItem(cb.ix, i), d2 Then
             pR.r.wsItem(cix, i) = (d1 * d2).ToString()
        else
             pR.r.wsItem(cix, i) = String.Empty
        End If
     Else
        pR.r.wsItem(cix, i) = String.Empty
     End If
 Next

Convert.ToDouble cannot handle the fact that a string is not a valid numeric value and if it encounter this case it throws an exception. Throwing an exception is costly in terms of perfomance in particular for gathering the information about the call stack.

Instead, if there is the possibility that your input contains values that cannot be converted to double, then Double.TryParse is the correct way to proceed also if your benchmarks show a little difference in performance. Double.TryParse doesn't raise an exception if the string passed cannot be converted to a double, but return false. In this way the costly exception is avoided and you have a more predictable time of execution

Said that, you should really reevaluate your approach to store every kind of data in some string structure. The need of constant conversion between a string and the intended data type could be a real bottleneck here.