When I write a large CSV-like file containing millions of double
values, the bottleneck appears to be the conversion of double to string.
What is the fastest way to append a double value to a StreamWriter
, with a fixed number of digits after the point?
Currently I use
// called once
System.Globalization.NumberFormatInfo nfi = new System.Globalization.NumberFormatInfo();
nfi.NumberDecimalDigits = 4;
// called millions of times in a loop
streamwriter.Write(mydouble.ToString(nfi));
If i write a constant string instead of a double, the program finishes 10 times faster.
If I write an int instead of a double, it is still more than twice as fast.
(All tests were executed in release mode, without a debugger attached)
What is the fastest way to convert this double to a string?
I have included a benchmark to illustrate my problem below:
I write 1 million doubles to a file, 100 times in a row.
The total time is 25.2 seconds. The loop with only double.ToString, and no streamwriter.Write finishes in 21 seconds. The loop with only streamwriter.Write finishes in 3.5 seconds
System.Globalization.NumberFormatInfo nfi = new System.Globalization.NumberFormatInfo();
nfi.NumberDecimalDigits = 4;
double d = 0.1234;
Stopwatch watch;
watch = Stopwatch.StartNew();
for (int i = 0; i < 100; i++)
{
using (StreamWriter sw = new StreamWriter(@"c:\temp\test.txt", false, Encoding.UTF8, 65536))
{
for (int j = 0; j < 1000000; j++)
{
sw.Write(d.ToString(nfi));
}
}
}
Console.WriteLine("stream.Write & double.ToString: {0}", watch.ElapsedMilliseconds);
watch = Stopwatch.StartNew();
for (int i = 0; i < 100; i++)
{
using (StreamWriter sw = new StreamWriter(@"c:\temp\test.txt", false, Encoding.UTF8, 65536))
{
for (int j = 0; j < 1000000; j++)
{
sw.Write("0.1234");
}
}
}
Console.WriteLine("only stream.Write: {0}", watch.ElapsedMilliseconds);
watch = Stopwatch.StartNew();
for (int i = 0; i < 100; i++)
{
using (StreamWriter sw = new StreamWriter(@"c:\temp\test.txt", false, Encoding.UTF8, 65536))
{
for (int j = 0; j < 1000000; j++)
{
string s = d.ToString(nfi);
}
}
}
Console.WriteLine("only double.ToString: {0}", watch.ElapsedMilliseconds);