Grumble: performance hit using String.ToDouble vs Val

I have been working to improve the performance of some code that processes large amounts of text, a large portion of which is turned into numerics, and I wondered if it might make sense to replace API1’s trusty old Val() with API2’s shiny new String.ToDouble. Sure enough, there’s a significant performance difference between them. Running a loop 100,000 times produces the following results:

API1 - Val(): 10,540 milliseconds

API2 - String.ToDouble: 52,966 milliseconds

That’s a nearly perfect 5X difference. The API1 call is 5 times faster than the API2 call.

My code already uses Val(), so no further action is needed on this project – but this calls into question what should be considered best practices with regards to API2. Val() and String.ToDouble produce identical numeric results; there are no ergonomic differences between their usages; the only factor String.ToDouble has in its favor is some vague hand-waving about it being the more current terminology for the language and that API1 will go away some day.

I suspect that the other String.* functions that have static equivalents are equally slow, because in my performance tuning of the project, I’ve discovered that one of the most significant factors is calling a class method: the overhead of making a method call often dwarfs whatever is inside that method to a shocking extent. Flattening the call tree can produce significant performance gains without changing much of the underlying code that does the actual work.

So – what’s to be done? I can’t honestly recommend API2 due to this kind of performance hit that might be lurking behind some functionality. Surely, since these are static calls (the String.ToDouble call is invariant across all instances of the class), the compiler could safely transform them into the internal equivalent of whatever happens when the code calls Val()?

I gather the API2 raises exceptions if the passed string is not numeric.

Maybe thats the problem.

(TBH - I don’t see that as a feature.. I’m happy for an invalid string to return 0, but hey ho…)

Val does always uses “.” as a decimal separator. Many countries use “,” if this is important to you then val won’t work correctly.

As Ian stated, String.Val() uses US thousands and decimal separators always. So it makes the internal code more efficient not needing being locale aware.

It looks like toDouble does some cleanup of the string parameter before it gets evaluated, which might explain some of the performance hit. At least Val is still a current method.

What if the test using Val included cleaning the string before each execution?

Nope, the real performance hit is firing ICU libs to use localization services for numbers and time

Thanks, everybody. That makes a lot of sense. In my case, the text I am processing is computer generated and always uses a generic ±1.23e45 format so Val does the trick.

And API 2 s.Val times are almost as good as API 1 Val(s)