我做了非常簡單的C#和F#測試程序。爲什麼LINQ(c#)與Seq(f#)之間有性能差異
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace ConsoleApplication2
{
class Program
{
static int Remainder(int num)
{
return num % 2;
}
static int SumOfremainders(IEnumerable<int> list)
{
var sum = 0;
foreach (var num in list)
{
sum += Remainder(num);
}
return sum;
}
static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
var nums = Enumerable.Range(1, 10000000);
sw.Start();
var a = SumOfremainders(nums);
sw.Stop();
Console.WriteLine("Duration " + (sw.ElapsedMilliseconds));
Console.WriteLine("Sum of remainders: {0}", a);
}
}
}
let remainder x = x % 2
let sumORemainders n =
n
|> Seq.map(fun n-> remainder n)
|> Seq.sum
let seqb = Seq.init 10000000(fun n->n)
let timer =System.Diagnostics.Stopwatch()
timer.Start()
let a =(sumORemainders seqb)
timer.Stop()
printfn "Elapsed Time: "
System.Console.WriteLine timer.ElapsedMilliseconds
printfn "Sum of squares of 1-100: %d" a
[<EntryPoint>]
let main argv =
0 // return an integer exit code
C#71毫秒 F#1797毫秒
我從F#第二版本,其工作相似比C#
let remainder x = x % 2
let sumORemainders (input:seq<int>) =
let mutable sum = 0
let en = input.GetEnumerator()
while (en.MoveNext()) do
sum <- sum + remainder en.Current
sum
let seqb = Seq.init 10000000(fun n->n)
let timer =System.Diagnostics.Stopwatch()
timer.Start()
let a =(sumORemainders seqb)
timer.Stop()
printfn "Elapsed Time: "
System.Console.WriteLine timer.ElapsedMilliseconds
printfn "Sum of squares of 1-100: %d" a
[<EntryPoint>]
let main argv =
0 // return an integer exit code
但結果不是未顯著(1650ms)
改變我不明白這兩種語言在速度上的巨大差異。
這兩個程序具有非常相似的IL代碼,都使用IEnumerable,而且F#用函數替換函數調用。
我重寫了基於f#IL代碼的c#代碼。
static int SumOfremainders(IEnumerable<int> list)
{
var sum = 0;
IEnumerator<int> e = list.GetEnumerator();
while (e.MoveNext())
{
sum += e.Current % 2;
}
return sum;
}
兩個程序的IL代碼是相同的,但速度還是有很大差別。 我發現IL差別感謝霧搜索
,慢速代碼
[CompilationMapping(SourceConstructFlags.Module)]
public static class Program
{
[Serializable]
internal class [email protected] : FSharpFunc<int, int>
{
internal [email protected]()
{
}
public override int Invoke(int n)
{
return n;
}
}
[CompilationMapping(SourceConstructFlags.Value)]
public static IEnumerable<int> seqb
{
get
{
return [email protected];
}
}
快速代碼
[CompilationMapping(SourceConstructFlags.Module)]
public static class Program
{
[CompilationMapping(SourceConstructFlags.Value)]
public static int[] seqb
{
get
{
return [email protected];
}
}
我不同意這個問題是重複的。另一個問題是公開的,而這更具體。但是我認爲OP應該改寫這個問題來包含'Seq/LINQ',因爲這很可能是問題('LINQ'很慢'Seq'慢) – FuleSnabel
這是因爲你的C#代碼和F#實際上是不同的。 –
此:'讓seqb = Seq.init 10000000(樂趣N-> N)'不等於'VAR NUMS = Enumerable.Range(1,10000000);' –