Alois has put up a contest for getting the fastest Time format function http://geekswithblogs.net/akraus1/archive/2006/04/23/76146.aspx
Submitted by Bruce Dunwiddie
private static string FormatFast(DateTime time)
{
char[] dateData = new char[12];
dateData[0] = (char)(time.Hour / 10 + '0');
dateData[1] = (char)(time.Hour % 10 + '0');
dateData[2] = ':';
dateData[3] = (char)(time.Minute / 10 + '0');
dateData[4] = (char)(time.Minute % 10 + '0');
dateData[5] = ':';
dateData[6] = (char)(time.Second / 10 + '0');
dateData[7] = (char)(time.Second % 10 + '0');
dateData[8] = '.';
dateData[9] = (char)(time.Millisecond / 100 + '0');
dateData[10] = (char)(time.Millisecond / 10 % 10 + '0');
dateData[11] = (char)(time.Millisecond % 10 + '0');
return new string(dateData);
}
This is a good start but can be optimized alot further ...
private unsafe static string FormatFast3(DateTime time)
{
char[] dateData = new char[12];
fixed (char* p = dateData)
{
long ticks = time.Ticks;
char* a = p;
int hour = (int)((ticks / 0x861c46800L)) % 24;
int minute = (int)((ticks / 0x23c34600L)) % 60;
int second = (int)(((ticks / 0x989680L)) % 60L);
int ms = (int)(((ticks / 0x2710L)) % 0x3e8L);
*a = (char)(hour / 10 + '0');
a++;
*a = (char)(hour % 10 + '0');
a++;
*a = ':';
a++;
*a = (char)(minute / 10 + '0');
a++;
*a = (char)(minute % 10 + '0');
a++;
*a = ':';
a++;
*a = (char)(second / 10 + '0');
a++;
*a = (char)(second % 10 + '0');
a++;
*a = '.';
a++;
*a = (char)(ms / 100 + '0');
a++;
*a = (char)(ms / 10 % 10 + '0');
a++;
*a = (char)(ms % 10 + '0');
}
return new String(dateData);
}
The huge time saver was only getting ticks as a property then calculating the rest myself (in particular since these are calculated properties and the above code calls into them multiple times). The other major change was to use unsafe array access which turned out to be a little bit faster (the aray access comes out to be arraybase + (index * typesize) where as the unsafe is location + constant. Also I used a little bit of trickery on the hours and minutes calculations by converting to an int before the modulus thus running the modulus on 32 bit values instead of on 64 bit.When all is said and done here are my results for 10 million operations (averaged over 10 runs).
With StringFormat 00:00:29.0796462
With StringFormat 00:00:27.7783141
With FastFormat 00:00:13.2886650
With FastFormat3 00:00:05.8365522
private unsafe static string FormatFast4(DateTime time)
{
char[] dateData = { ' ', ' ', ':', ' ', ' ', ':', ' ', ' ', '.', ' ', ' ', ' ' };
fixed (char* p = dateData)
{
long ticks = time.Ticks;
char* a = p;
int hour = (int)((ticks / 0x861c46800L)) % 24;
int minute = (int)((ticks / 0x23c34600L)) % 60;
int second = (int)(((ticks / 0x989680L)) % 60L);
int ms = (int)(((ticks / 0x2710L)) % 0x3e8L);
*a = (char)(hour / 10 + '0');
a++;
*a = (char)(hour % 10 + '0');
a+=2;
*a = (char)(minute / 10 + '0');
a++;
*a = (char)(minute % 10 + '0');
a+=2;
*a = (char)(second / 10 + '0');
a++;
*a = (char)(second % 10 + '0');
a+=2;
*a = (char)(ms / 100 + '0');
a++;
*a = (char)(ms / 10 % 10 + '0');
a++;
*a = (char)(ms % 10 + '0');
}
return new String(dateData);
}
Appears to be a little bit faster even!! down to .6 seconds for 1 million on my machine WITH recreating the char array for every call (other metrics were with a static array).