[英]C# Double.ToString() performance issue
我有以下方法将double数组转换为List<string>
:
static Dest Test(Source s)
{
Dest d = new Dest();
if (s.A24 != null)
{
double[] dd = s.A24;
int cnt = dd.Length;
List<string> lst = new List<string>();
for (int i = 0; i < cnt; i++)
lst.Add(((double)dd[i]).ToString());
d.A24 = lst;
}
else
{
d.A24 = null;
}
return d;
}
根据我的基准测试,在循环中执行List.Add()似乎是最快的方式,击败所有各种LINQ和转换技巧。
这真的很慢。 一百万次呼叫2400ms(任何CPU,更喜欢64位)。 所以我正在尝试各种方法来加快速度。 我们假设我无法缓存源列表或目标列表等。
所以无论如何,我偶然发现了一些奇怪的东西...如果我将lst.Add()行改为强制转换为十进制而不是双精度,那么它会更快,更快。 900毫秒vs 2400毫秒。
这是我的问题
1)十进制有更高的准确性然后加倍,所以我不应该在类型转换中丢失任何东西,对吗?
2)为什么Decimal.ToString()比Double.ToString()快得多?
3)这是一个合理的优化,还是我错过了一些关键的细节,它会回来咬我?
我并不担心使用更多的内存,我只关心性能。
此时测试数据没有任何复杂功能,只需使用:
s.A24 = new double[] { 1.2, 3.4, 5.6 };
为了它的价值,我运行了以下内容并获得了不同的结果,十进制通常需要稍长一些(但是对lst.Add()和number.ToString()的调用的调用大致相同)。
您的代码中的A24是什么类型的集合? 如果您看到的额外开销实际上是在投射或者您当前没有看到的东西,我不会感到惊讶。
var iterations = 1000000;
var lst = new List<string>();
var rnd = new Random();
var dblArray = new double[iterations];
for (var i = 0; i < iterations; i++)
//INTERESTING FINDING FROM THE COMMENTS
//double.ToString() is faster if this line is rnd.NextDouble()
//but decimal.ToString() is faster if hard-coding the value "3.5"
//(despite the overhead of casting to decimal)
dblArray[i] = rnd.NextDouble();
var sw = new Stopwatch();
sw.Start();
for (var i = 0; i < iterations; i++)
lst.Add(dblArray[i].ToString());
sw.Stop();
//takes 280-300 MS
Debug.WriteLine("Double loop MS: " + sw.ElapsedMilliseconds);
//reset list
lst = new List<string>();
sw.Restart();
for (var i = 0; i < iterations; i++)
lst.Add(((decimal)dblArray[i]).ToString());
sw.Stop();
//takes 280-320 MS
Debug.WriteLine("Decimal loop MS: " + sw.ElapsedMilliseconds);
十进制和双数通常是混淆和互换的,但它们在处理器级别上是完全不同的动物。 如果我不得不想象为Double.ToString()编写代码,我可以看到问题......这很难。 相比之下,编写Decimal.ToString()的代码应该比Int32.ToString()困难得多。 我敢肯定,如果你将Int32.ToString()与Decimal.ToString()进行比较,你会发现它们的结果非常接近。
仅供参考:Double和Float(单曲)不精确,许多数字不能用Double表示。 在你的例子中,你给出1.2这实际上是1 + 1/5。 这不能作为一个真正的双重存在(即使VS IDE涵盖它)。 你会得到类似1.1999999999999998的东西。 如果您想要性能,请使用十进制。
2)为什么Decimal.ToString()比Double.ToString()快得多?
因为Double.ToString()
实际上要复杂得多。 比较Decimal.ToString()和Double.ToString()的核心实现, Decimal.ToString()
具有固定的精度,而Double.ToString()
的精度是按需的。 Double
有它的IEEE浮点定义 ,它也比Decimal
复杂得多。
当前的Double.ToString()
实现依赖于Windows上的_ecvt
和Linux上的snprintf
。 它们效率低下(特别是对于Linux实现)。 有一个正在进行的PR以一种有效的方式重写Double.ToString()
,它消除了_ecvt
和snprintf
的依赖关系。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.