col*_*ang 6 c# performance f# pattern-matching
我对模式匹配的性能有点好奇,所以我做了以下测试:
poolEven 包含10000个元素0,1,2,3,(2500相等)
testSize = 100000
IfelseEven(100000) 花费650毫秒(开关会更快,但我没有附加代码),而MatchEven(100000)需要7000毫秒,这是10倍的时间
性能下降是否来自Array.Fold?我100%肯定,如果我IEnumerable.Aggregate的速度会大大降低.但我认为F#处理Array.Fold比C#更好IEnumerable.Aggregate.我想比较两种语言中最常见(等效)编码方式的性能,而不是使它们相同的严格方法.
测试在x64版本中完成,平均10次试验进行适当的预热
C#:
public void IfelseEven(int testSize)
{
Ifelse(testSize, poolEven);
}
void Ifelse(int testSize, int[] pool)
{
long sum = 0;
for (int i = 0; i < testSize; i++)
{
for (int j = 0; j < poolCapacity;j++ )
{
var item = pool[j];
if (item == 0)
{
sum += 5;
}
else if (item == 1)
{
sum += 1;
}
else if (item == 2)
{
sum += 2;
}
else if (item == 3)
{
sum += 3;
}
else
{
sum += 4;
}
}
}
}
public void MatchEven(int testSize)
{
PatternMatch.myMatch(testSize, poolEven);
}
Run Code Online (Sandbox Code Playgroud)
F#:
module PatternMatch
let mat acc elem =
acc +
match elem with
| 0 -> 5L
| 1 -> 1L
| 2 -> 2L
| 3 -> 3L
| _ -> 4L
let sum (pool:int[])=
Array.fold mat 0L pool;
let myMatch testSize pool=
let mutable tmp = 0L
for i=0 to testSize do
tmp <- sum(pool) + tmp
tmp
Run Code Online (Sandbox Code Playgroud)
Dan*_*iel 11
投票结束 - 我们可以整天玩这个游戏.有关为什么不同的代码可能具有不同的执行时间的更多评论,请参阅此问题和答案.如果您只想加快F#功能,请尝试以下方法:
let ifElse testSize (pool: _[]) =
let mutable sum = 0L
for i = 0 to testSize - 1 do
for j = 0 to pool.Length - 1 do
match pool.[j] with
| 0 -> sum <- sum + 5L
| 1 -> sum <- sum + 1L
| 2 -> sum <- sum + 2L
| 3 -> sum <- sum + 3L
| _ -> sum <- sum + 4L
sum
Run Code Online (Sandbox Code Playgroud)
通过我的测量,这方便地舔C#功能(它仍然更短,更可读):
C#5655
F#4003
顺便说一句,leppie在评论中钉了它.我描述了你的代码,78%的时间花在了Array.fold- 在一个紧凑的循环中不好.
正如评论中所提到的,通过使用完全不同的模式,您实际上并没有真正得到matchvs if/elseif的隔离比较.循环与折叠与递归的比较是一个完全不同的问题.
使用更直接的比较(循环,与Daniel的响应相同),我得到了以下结果.发布版本,.NET 4.5,x64目标arch.
C#和F#if\elseif方法几乎完全相同(在这个人为的例子中).
F#match一直比if\elseif任何一种语言都快(在这个人为的例子中)
C#switch一直是最快的(在这个人为的例子中).
| 归档时间: |
|
| 查看次数: |
1743 次 |
| 最近记录: |