我和我的同事比較了傳遞lambda表達式進行工作時C#函數的速度與內聯函數關於做工時間的關係。我們發現在將lambda投影傳遞給C#select函數(例如)時會產生成本,並希望查看F#是否具有相同的問題,或者如果它做了不同的事情。爲什麼減少速度比sum或sumBy快?
無論我們原來的意圖如何,我們偶然發現了一些我們無法弄清楚的東西。在下面的例子中,我們總結名單3種不同的方式
- 減少
- 總和
- SumBy
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
這麼明顯的減少是這裏的大贏家。在反編譯中,我可以看到減少得到降低
[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;
}
}
但我很難搞清楚總結和sumBy正在做什麼。時間偏差從哪裏來?
目前的答案表明,減少快5倍,因爲最初我給減少一個未檢查操作。但是,更新的測試使用檢查操作員(從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說得對。 Checked算術必須將事情減慢很多。 –
@OnorioCatenacci,我用檢查過的arithemtic運行測試,它沒有區別 – devshorts