Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I improve the performance of code using DateTime.ToString?

Tags:

In my binary to text decoding application (.NET 2.0) I found that the line:

logEntryTime.ToString("dd.MM.yy HH:mm:ss:fff") 

takes 33% of total processing time. Does anyone have any ideas on how to make it faster?

EDIT: This app is used to process some binary logs and it currently takes 15 hours to run. So 1/3 of this will be 5 hours.

EDIT: I am using NProf for profiling. App is processing around 17 GBytes of binary logs.

like image 939
Michal Sznajder Avatar asked Jul 24 '09 07:07

Michal Sznajder


People also ask

How to format DateTime string?

To do this, you use the "MM/yyyy" format string. The format string uses the current culture's date separator. Getting a string that contains the date and time in a specific format. For example, the "MM/dd/yyyyHH:mm" format string displays the date and time string in a fixed format such as "19//03//2013 18:06".

How to convert DateTime format to string in c#?

Convert DateTime to String using the ToString() MethodUse the DateTime. ToString() method to convert the date object to string with the local culture format. The value of the DateTime object is formatted using the pattern defined by the DateTimeFormatInfo.

How does DateTime work?

The DateTime value type represents dates and times with values ranging from 00:00:00 (midnight), January 1, 0001 Anno Domini (Common Era) through 11:59:59 P.M., December 31, 9999 A.D. (C.E.) in the Gregorian calendar. Time values are measured in 100-nanosecond units called ticks.


2 Answers

It's unfortunate that .NET doesn't have a sort of "formatter" type which can parse a pattern and remember it.

If you're always using the same format, you might want to hand-craft a formatter to do exactly that. Something along the lines of:

public static string FormatDateTime(DateTime dt) {     char[] chars = new char[21];     Write2Chars(chars, 0, dt.Day);     chars[2] = '.';     Write2Chars(chars, 3, dt.Month);     chars[5] = '.';     Write2Chars(chars, 6, dt.Year % 100);     chars[8] = ' ';     Write2Chars(chars, 9, dt.Hour);     chars[11] = ' ';     Write2Chars(chars, 12, dt.Minute);     chars[14] = ' ';     Write2Chars(chars, 15, dt.Second);     chars[17] = ' ';     Write2Chars(chars, 18, dt.Millisecond / 10);     chars[20] = Digit(dt.Millisecond % 10);      return new string(chars); }  private static void Write2Chars(char[] chars, int offset, int value) {     chars[offset] = Digit(value / 10);     chars[offset+1] = Digit(value % 10); }  private static char Digit(int value) {     return (char) (value + '0'); } 

This is pretty ugly, but it's probably a lot more efficient... benchmark it, of course!

like image 176
Jon Skeet Avatar answered Sep 29 '22 13:09

Jon Skeet


Are you sure it takes 33% of the time? How have you measured that? It sounds more than a little suspicious to me...

This makes things a little bit quicker:

Basic: 2342ms Custom: 1319ms 

Or if we cut out the IO (Stream.Null):

Basic: 2275ms Custom: 839ms 

using System.Diagnostics; using System; using System.IO; static class Program {     static void Main()     {         DateTime when = DateTime.Now;         const int LOOP = 1000000;          Stopwatch basic = Stopwatch.StartNew();         using (TextWriter tw = new StreamWriter("basic.txt"))         {             for (int i = 0; i < LOOP; i++)             {                 tw.Write(when.ToString("dd.MM.yy HH:mm:ss:fff"));             }         }         basic.Stop();         Console.WriteLine("Basic: " + basic.ElapsedMilliseconds + "ms");          char[] buffer = new char[100];         Stopwatch custom = Stopwatch.StartNew();         using (TextWriter tw = new StreamWriter("custom.txt"))         {             for (int i = 0; i < LOOP; i++)             {                 WriteDateTime(tw, when, buffer);             }         }         custom.Stop();         Console.WriteLine("Custom: " + custom.ElapsedMilliseconds + "ms");     }     static void WriteDateTime(TextWriter output, DateTime when, char[] buffer)     {         buffer[2] = buffer[5] = '.';         buffer[8] = ' ';         buffer[11] = buffer[14] = buffer[17] = ':';         Write2(buffer, when.Day, 0);         Write2(buffer, when.Month, 3);         Write2(buffer, when.Year % 100, 6);         Write2(buffer, when.Hour, 9);         Write2(buffer, when.Minute, 12);         Write2(buffer, when.Second, 15);         Write3(buffer, when.Millisecond, 18);         output.Write(buffer, 0, 21);     }     static void Write2(char[] buffer, int value, int offset)     {         buffer[offset++] = (char)('0' + (value / 10));         buffer[offset] = (char)('0' + (value % 10));     }     static void Write3(char[] buffer, int value, int offset)     {         buffer[offset++] = (char)('0' + (value / 100));         buffer[offset++] = (char)('0' + ((value / 10) % 10));         buffer[offset] = (char)('0' + (value % 10));     } } 
like image 28
Marc Gravell Avatar answered Sep 29 '22 13:09

Marc Gravell