1

I just came over a code that looks pretty much like this:

    public static string GetXmlAttributeValue(XmlNode Node, string attributeName, string defVal)
    {
        try
        {
            return Node.Attributes.GetNamedItem(attributeName).Value;
        }
        catch(Exception)
        {
            return defVal;
        }
    }

The ideea of this method is to try to get a node's attribute and return a default value if it has none. After changing the code to something like this:

    public static string GetXmlAttributeValue(XmlNode Node, string attributeName, string defVal)
    {
        if(Node.Attributes.GetNamedItem(attributeName) != null)
            return Node.Attributes.GetNamedItem(attributeName).Value;
        return defVal;
    }

I saw a drastic improvement in performance. To be a little more exact, on about 5000 calls to this function, the first implementation took about 2 seconds, while the second implementation is pretty much instant (i need to mention that the probability of the attribute not to exist is pretty high, so a lot of catch-es will occur).

My question is why does this happen? I google-ed how try catch works, but haven't found anything that could clarify my question

relysis
  • 938
  • 13
  • 26
  • 2
    The exception contains a StackTrace, walking the stack to build this trace is pretty expensive – Steve Jan 13 '17 at 14:11
  • 1
    And the setup required for transmitting control to the `catch` block is not free either. – Frédéric Hamidi Jan 13 '17 at 14:12
  • 1
    The second approach can even be improved because you are calling `Node.Attributes.GetNamedItem(attributeName)` twice. `var item = Node.Attributes.GetNamedItem(attributeName); return item?.Value ?? defVal;` – Tim Schmelter Jan 13 '17 at 14:12
  • As the name already lets assume an exception is something exceptional, so to say it´s not usual. If you come accros this behaviour quite often is it still exceptional? – HimBromBeere Jan 13 '17 at 14:14
  • The reason of that overhead is simply that creating an `Exception`-object requires some work (for instance building the stacktrace) which - when done repeadatly - can produce some perfomance-penalty. – HimBromBeere Jan 13 '17 at 14:17
  • If using C# 6, your second solution can become a single line: `Node.Attributes.GetNamedItem(attributeName)?.Value ?? defVal` – Najkin Jan 13 '17 at 14:17
  • @Riokmij Which is absoluetely unrelated to the question. – HimBromBeere Jan 13 '17 at 14:18
  • Exceptions are large objects. They have a block of text, a StackTrace, and often they have an InnerException which is a whole new Exception that also has its own text and StackTrace. Version two that you have there just does the check and tosses a boolean back. A real-world analogy might be to say that to use an Exception for flow control is like choosing to, instead of shutting an open door, build an entire structure on the other side of it. – CDove Jan 13 '17 at 14:18

1 Answers1

0

Short answer: there is a performance hit for using exceptions as a flow-control.

Quote from MSDN on the topic: Throwing exceptions can negatively impact performance. For code that routinely fails, you can use design patterns to minimize performance issues.

Forklift
  • 909
  • 11
  • 19