【发布时间】:2014-05-24 04:10:25
【问题描述】:
我和我的同事正在比较 C# 函数在传递 lambda 以完成工作时的速度与内联函数在工作所花费的时间方面的速度。我们发现您在将 lambda 投影传递给 C# 选择函数(例如)时会产生成本,并想看看 F# 是否有相同的问题,或者它是否做了不同的事情。
不管我们最初的意图是什么,我们偶然发现了一些我们无法弄清楚的东西。在以下示例中,我们将列表总结为 3 种不同的方式
- 减少
- 总和
- 总和
module fs
open NUnit.Framework
open FsUnit
open System
open System.Diagnostics;
[<Test>]
let sumTest() =
let nums = [0..1000]
let repeat = 100000
let stopWatch = new Stopwatch()
stopWatch.Start()
let sumsReduce =
[
for i in [0..repeat] do
yield List.reduce (+) nums
]
Console.WriteLine("reduce = {0} - Time = {1}", List.head sumsReduce, stopWatch.Elapsed.TotalSeconds);
stopWatch.Restart()
let sumsSum =
[
for i in [0..repeat] do
yield List.sum nums
]
Console.WriteLine("sum = {0} - Time = {1}", List.head sumsSum, stopWatch.Elapsed.TotalSeconds);
stopWatch.Restart()
let sumsSumBy =
[
for i in [0..repeat] do
yield List.sumBy id nums
]
Console.WriteLine("sumBy = {0} - Time = {1}", List.head sumsSumBy, stopWatch.Elapsed.TotalSeconds);
stopWatch.Restart()
输出如下:
reduce = 500500 - Time = 0.2725156
sum = 500500 - Time = 1.1183165
sumBy = 500500 - Time = 1.1126781
很明显,reduce 是这里的大赢家。在反编译中,我可以看到 reduce 被归结了
[Serializable]
internal class sumsReduce\u004021\u002D1 : OptimizedClosures.FSharpFunc<int, int, int>
{
internal sumsReduce\u004021\u002D1()
{
base.\u002Ector();
}
public override int Invoke(int x, int y)
{
return x + y;
}
}
但我很难弄清楚 sum 和 sumBy 在做什么。时间差异来自哪里?
当前的答案表明 reduce 快 5 倍,因为最初我给 reduce 一个未经检查的运算符。但是,更新测试以使用检查运算符(来自 Checked 模块),我仍然得到相同的结果
let sumsReduce =
[
for i in [0..repeat] do
yield List.reduce (Checked.(+)) nums
]
请注意时间差异仍然存在
reduce = 500500 - Time = 0.274697
sum = 500500 - Time = 1.1126796
sumBy = 500500 - Time = 1.1370642
【问题讨论】:
-
我很愿意相信@ildjarn 做对了。检查算术必须减慢速度。
-
@OnorioCatenacci,我用检查算术运行了测试,没有任何区别
标签: f#