Poor Performance with DateTime.Parse()

We traced a performance bottleneck to a single function recently. Interestingly enough, this function has been in existence (running in a production environment in all of its glory) for roughly 4 years now. Only now that we are required to execute the offending piece of code approximately 10 million times within a short four hour window has the problem actually surfaced.Our function has about 100 LOC. It contains custom collection class references, string manipulation, financial calculations and numerous other operations which I would flag as suspicious. We successfully avoided performance counters and simply stepped through the code after ensuring we had set an adequate number of timespan variables to track execution times the old fashion way. As it works out, DateTime.Parse we the bottleneck and our simple logic to determine is IsDate() or IsDatePast() might as well have been the most complicated, resource-eating routines on the planet.Why was this? Well, the Parse method tries very hard to make sense of the string that’s passed to it in order to create a valid DateTime value. It ignores leading and trailing white space, and unrecognized characters if possible, and it fills in missing information with the corresponding current date and time values. Parse will throw a FormatException if it’s unable to decipher the string you send to it, but otherwise, it bends over backwards for you. Our guess is it tries to do too much for its own good and exhausts itself in the process.We tried to replace the Parse method with the other DateTime static method — ParseExact — but it didn’t provide much relief.In the end, we got creative. We opted to create a simple function which first instantiates a new DateTime reference by using the month, day and year from the string representation of the date. (We were lucky because we knew this string would either be in the MM/DD/YYYY format or emtpy.)  Would you believe that splitting our string and then constructing a new DateTime reference performed considerably better than using the standard DateTime.Parse method?  Well, it did.

1: ///<summary> 2: ///Do not rely on the DateTime.Parse() method 3: ///Check if date is in the past by splitting string, 4: ///building datetime object then compare against today 5: ///</summary> 6: ///<param name=”sDate”>Date to Check</param> 7: ///<returns>False if greater than today</returns>8: public static bool IsDatePastParse(string sDate) 9: { 10: try 11: { 12: if (sDate.Length > 0) 13: { 14: string[] dt = sDate.Split(‘/’); 15: return IsDatePast(16: new DateTime(Convert.ToInt32(dt[2]), 17: Convert.ToInt32(dt[0]),18: Convert.ToInt32(dt[1])));19: } 20: else 21: {22: // Invalid if no date is passed 23: return false; 24: } 25: } 26: catch 27: { 28: // Assume the string was an invalid date29: return false; 30: } 31: } 32:  33: ///<summary> 34: ///Has the date past? Compare against today’s date. 35: ///</summary> 36: ///<param name=”dtDate”>Date to Check</param> 37: ///<returns>False if date is in the past</returns>38: public static bool isDatePast(DateTime dtDate) 39: { 40: // Consider today in the past41: if (DateTime.Today.Date >= dtDate.Date) 42: return true; 43: else 44: return false; 45:

Comments

  1. I found a bottleneck in some work code which turned out to be DateTime.Parse as well.

    I used the dotTrace profiler (pre-release 2.0) to find the bottleneck:
    http://www.jetbrains.com/profiler/features/
    which showed how much time was being spent in that function.

    To peak into the function itself to see what’s going on, there’s always Reflector:
    http://www.aisto.com/roeder/dotnet/

    If you dig into the implementation, there’s an internal method “DateTimeParse.Lex” that’s doing very complicated token parsing (which in turn calls other lexing methods internally.)

    Basically, a big mess if you know you’re going to get the date in specific format.

  2. The fact that your solution works faster is probably caused by the fact that you know the format of the date and DateTime.Parse does not – i.e.: it probably takes into consideration local settings, the thread culture etc, while you know exactly what is the date format.
    Other than that – a nice find! Thanks

  3. Hi Johnny,

    I’m very sorry to be off topic here but I’d like to ask if you use any plugin to display the code in wordpress because it’s looking great. Couldn’t find any contact form, I would be pleased if you answer me – if you want via e-mail and delete this comment.

    Cheers
    Andy

  4. Adam, thanks for drilling into the details. I appreciate the feedback. (And sorry your comment didn’t post immediately. Since you included more than one link it was held for moderation temporarily. I’m going to have to work on this because if you are anything like me you like instant gratification and would like to see your comments immediately.) Thanks again.

  5. No worries, Andy. I’m using plenty of plugins, but I’m not sure they contribute to the overall look of the site. I’ll put an article together outlining the details later today. Thanks for the interest.

  6. Wow! This could be one particular of the most beneficial blogs We’ve ever arrive across on this subject. Actually Fantastic. I’m also an expert in this topic so I can understand your hard work.

  7. I just couldn’t go away your site before suggesting that I really loved the usual information a person supply to your visitors? Is going to be again regularly in order to investigate cross-check new posts.

  8. Howdy! This is my 1st comment here so I just wanted to give a quick shout out and say I genuinely enjoy reading your articles. Can you recommend any other blogs/websites/forums that deal with the same subjects? Thank you!

  9. Thus , merely by make use of items the whole thing, the complete planet could be described as delivered electronically a little bit far more. In which sometimes holds the specific And also carbon undoubtedly pumped back to conditions more than these manufacturing debt settlements. every day deal livingsocial discount baltimore washington

closed