Zrobiłem bardzo proste programy testowe C# i F #.Dlaczego występuje różnica wydajności między LINQ (C#) a 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 MS f # 1797 MS
że wykonane drugą wersję z F #, które działają podobnie niż 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
ale wynik nie znacząco (1650ms)
zmienione Nie rozumiem dużej różnicy w szybkości między dwoma językami.
Dwa programy mają bardzo podobny kod IL, oba używają IEnumerable, ponadto F # zastępuje wywołanie funkcji operacją.
Przepiszę kod C# na podstawie kodu f # IL.
static int SumOfremainders(IEnumerable<int> list)
{
var sum = 0;
IEnumerator<int> e = list.GetEnumerator();
while (e.MoveNext())
{
sum += e.Current % 2;
}
return sum;
}
Kod IL dwóch programów jest taki sam, ale prędkość nadal jest bardzo różna. znalazłem Il difference dzięki za Foggy Finder
Powolne kodu
[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];
}
}
Szybko kodu
[CompilationMapping(SourceConstructFlags.Module)]
public static class Program
{
[CompilationMapping(SourceConstructFlags.Value)]
public static int[] seqb
{
get
{
return [email protected];
}
}
Nie zgadzam się, że pytanie jest duplikatem. Drugie pytanie jest otwarte, podczas gdy jest ono o wiele bardziej szczegółowe. Jednak uważam, że PO powinien przeformułować pytanie tak, aby zawierało "Seq/LINQ", ponieważ jest to bardziej prawdopodobne, że problem ("LINQ" jest powolny "Seq" jest wolniejszy) – FuleSnabel
Wynika to z faktu, że kod C# i F # są w rzeczywistości różne. –
to: 'let seqb = Seq.init 10000000 (zabawa n-> n)' nie jest równe 'var nums = Enumerable.Range (1, 10000000);' –