C# ConvertTo Vs Parse
This article details the benchmark and performance showdown: C# ConvertTo vs Parse methods.
In any programming language, data type conversions are inevitably going to happen. C# programmers have quite a few tools up their sleeves thanks to the .Net framework.
A few popular methods for each data type include:
- ConvertTo
- Parse
- TryParse
- Try-Catch exception handling
and so on.
What isn’t often considered are the performance implications.
For the purposes of this article, we’ll be examining the performance implications of the first two with:
- int.Parse() vs Convert.ToInt32()
- bool.Parse() vs Convert.ToBoolean()
- DateTime.Parse() vs Convert.ToDateTime()
TryParse and the Try-Catch construct have already been examined in detail.
Ready? Let’s Go!
Getting Started
3 string arrays are initialized with 20 string representations of int, bool, and DateTime values. These will be the fixed values we’ll be converting for every run.
The code then performs the conversions using the associated Parse() and ConvertTo() methods.
The C# is written in Visual Studio 2015 targeting .Net Framework version 4.7.1 x64. The source code is available at the end of this blog so you can benchmark it on your own system.
Who won?
Let’s see what happened on my machine.
All times are indicated in seconds.milliseconds format.
Lower numbers indicate faster performance.
|
1,000 |
10,000 |
100,000 |
1,000,000 |
10,000,000 |
00.0000892 |
00.0008375 |
00.0086945 |
00.0727122 |
00.8015826 |
|
00.0005854 |
00.0010939 |
00.0075113 |
00.0777216 |
00.7841260 |
|
|
|||||
00.0000237 |
00.0001189 |
00.0011681 |
00.0116875 |
00.1037218 |
|
00.0000150 |
00.0001580 |
00.0010781 |
00.0115476 |
00.1136900 |
|
|
|||||
00.0031217 |
00.0099275 |
00.1080647 |
01.0871715 |
11.0092108 |
|
00.0015126 |
00.0102976 |
00.0994469 |
01.0265536 |
10.5169374 |
The winner is –
– nobody. That’s right.
Nobody.
Unless someone spots a flaw in my code, there’s really no clear cut winner when it comes to speed.
The times flipped back and forth after several runs with no discernible pattern.
What can I say? We’re calling this one a draw.
So should you use the ConvertTo or Parse methods?
Well, assuming you’re not concerned about exceptions or null values, y’know that old saying… ta-may-toe or tah-mah-toe.
The Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
using System; using System.Collections.Generic; using System.Collections; using System.Collections.Concurrent; using System.Data; using System.Data.Sql; using System.IO; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Threading; using System.Diagnostics; namespace TestApplication { class Program { static void Main(string[] args) { DateTime end; DateTime start = DateTime.Now; Console.WriteLine("### Overall Start Time: " + start.ToLongTimeString()); Console.WriteLine(); TestConvertToVsParse(1000); TestConvertToVsParse(10000); TestConvertToVsParse(100000); TestConvertToVsParse(1000000); TestConvertToVsParse(10000000); end = DateTime.Now; Console.WriteLine(); Console.WriteLine("### Overall End Time: " + end.ToLongTimeString()); Console.WriteLine("### Overall Run Time: " + (end - start)); Console.WriteLine(); Console.WriteLine("Hit Enter to Exit"); Console.ReadLine(); } //#################################################### //Compare the speed differences between Convert.ToDouble Vs double.TryParse //We're assuming no exceptions so we don't implement exception //handling which will affect code performance. //Code from http://cc.davelozinski.com static void TestConvertToVsParse(int numberOfIterations) { Console.WriteLine("######## " + System.Reflection.MethodBase.GetCurrentMethod().Name); Console.WriteLine("Number of values to convert: " + numberOfIterations.ToString("#,##0")); Stopwatch sw = new Stopwatch(); DateTime end = DateTime.Now; DateTime start = DateTime.Now; int initializecount = 20; string[] i = new string[initializecount]; string[] b = new string[initializecount]; string[] dt = new string[initializecount]; int i_result; bool b_result; DateTime dt_result; //Initialize the arrays which hold the values we'll be parsing //making sure that at least 1 will always throw an exception. //1 out of every 20 == 5%, which I think a fair estimate //to say 5% of data will be bad. for (int x = 0; x < initializecount; x++) { //create valid strings that we'll be later parsing i[x] = x.ToString(); b[x] = true.ToString(); dt[x] = (new DateTime()).ToString(); } Console.WriteLine("###########################################################"); Console.WriteLine("Starting int.Parse() test " + numberOfIterations.ToString("#,##0") + " at: " + DateTime.Now.ToLongTimeString()); sw.Restart(); for (int x = 0; x < numberOfIterations; x++) { i_result = int.Parse(i[x % initializecount]); } sw.Stop(); Console.WriteLine("Finished at: " + DateTime.Now.ToLongTimeString()); Console.WriteLine("Time to run: " + sw.Elapsed.ToString("mm\\:ss\\.fffffff")); Thread.Sleep(500); Console.WriteLine("###########################################################"); Console.WriteLine("Starting Convert.ToInt32() test " + numberOfIterations.ToString("#,##0") + " at: " + DateTime.Now.ToLongTimeString()); sw.Restart(); for (int x = 0; x < numberOfIterations; x++) { i_result = Convert.ToInt32(i[x % initializecount]); } sw.Stop(); Console.WriteLine("Finished at: " + DateTime.Now.ToLongTimeString()); Console.WriteLine("Time to run: " + sw.Elapsed.ToString("mm\\:ss\\.fffffff")); Thread.Sleep(500); Console.WriteLine("###########################################################"); Console.WriteLine("Starting bool.Parse() test " + numberOfIterations.ToString("#,##0") + " at: " + DateTime.Now.ToLongTimeString()); sw.Restart(); for (int x = 0; x < numberOfIterations; x++) { b_result = bool.Parse(b[x % initializecount]); } sw.Stop(); Console.WriteLine("Finished at: " + DateTime.Now.ToLongTimeString()); Console.WriteLine("Time to run: " + sw.Elapsed.ToString("mm\\:ss\\.fffffff")); Thread.Sleep(500); Console.WriteLine("###########################################################"); Console.WriteLine("Starting Convert.ToBoolean() test " + numberOfIterations.ToString("#,##0") + " at: " + DateTime.Now.ToLongTimeString()); sw.Restart(); for (int x = 0; x < numberOfIterations; x++) { b_result = Convert.ToBoolean(b[x % initializecount]); } sw.Stop(); Console.WriteLine("Finished at: " + DateTime.Now.ToLongTimeString()); Console.WriteLine("Time to run: " + sw.Elapsed.ToString("mm\\:ss\\.fffffff")); Thread.Sleep(500); Console.WriteLine("###########################################################"); Console.WriteLine("Starting DateTime.Parse() test " + numberOfIterations.ToString("#,##0") + " at: " + DateTime.Now.ToLongTimeString()); sw.Restart(); for (int x = 0; x < numberOfIterations; x++) { dt_result = DateTime.Parse(dt[x % initializecount]); } sw.Stop(); Console.WriteLine("Finished at: " + DateTime.Now.ToLongTimeString()); Console.WriteLine("Time to run: " + sw.Elapsed.ToString("mm\\:ss\\.fffffff")); Thread.Sleep(500); Console.WriteLine("###########################################################"); Console.WriteLine("Starting Convert.ToDateTime() test " + numberOfIterations.ToString("#,##0") + " at: " + DateTime.Now.ToLongTimeString()); sw.Restart(); for (int x = 0; x < numberOfIterations; x++) { dt_result = Convert.ToDateTime(dt[x % initializecount]); } sw.Stop(); Console.WriteLine("Finished at: " + DateTime.Now.ToLongTimeString()); Console.WriteLine("Time to run: " + sw.Elapsed.ToString("mm\\:ss\\.fffffff")); Console.WriteLine(); } } //class } //namespace |