我工作的一些沉重的CPU绑定的问题。 我看到一个大的性能提升,当我使用inline
关键字。 我创建标准的.NET库字典传递一个自定义键比较看下面的代码和时序结果
https://gist.github.com/4409734
而对Eq_cmp inline关键字
> perf_run 10000000 ;;
Real: 00:00:11.039, CPU: 00:00:11.029, GC gen0: 771, gen1: 3, gen2: 1
val it : unit = ()
使用上Eq_cmp inline关键字
perf_run 10000000 ;;
Real: 00:00:01.319, CPU: 00:00:01.388, GC gen0: 1, gen1: 1, gen2: 1
val it : unit = ()
>
我也注意到在第0 GC与内嵌代码和非联的代码量的巨大差异。
有人能解释一下为什么会出现如此巨大的差异?
加入后,我可以重现我的机器有3倍的性能提升上的行为inline
关键字。
下反编译两个版本并排ILSpy给出几乎相同的C#代码。 值得注意的区别是两个平等的测试:
// Version without inline
bool IEqualityComparer<Program.Pair<a>>.System-Collections-Generic-IEqualityComparer(Program.Pair<a> x, Program.Pair<a> y)
{
a v@ = x.v@;
a v@2 = y.v@;
if (LanguagePrimitives.HashCompare.GenericEqualityIntrinsic<a>(v@, v@2))
{
a w@ = x.w@;
a w@2 = y.w@;
return LanguagePrimitives.HashCompare.GenericEqualityIntrinsic<a>(w@, w@2);
}
return false;
}
// Version with inline
bool IEqualityComparer<Program.Pair<int>>.System-Collections-Generic-IEqualityComparer(Program.Pair<int> x, Program.Pair<int> y)
{
int v@ = x.v@;
int v@2 = y.v@;
if (v@ == v@2)
{
int w@ = x.w@;
int w@2 = y.w@;
return w@ == w@2;
}
return false;
}
通用平等比专业版的效率要低得多。
我也注意到在第0 GC与内嵌代码和非联的代码量的巨大差异。
有人能解释一下为什么会出现如此巨大的差异?
考虑看看GenericEqualityIntrinsic
函数F#源代码 :
let rec GenericEqualityIntrinsic (x : 'T) (y : 'T) : bool =
fsEqualityComparer.Equals((box x), (box y))
它的参数拳,这也解释了垃圾在你的第一个例子中,显著量。 当GC进场过于频繁,这将显着减慢计算。 (使用第二示例inline
)几乎不产生垃圾时Pair
是结构体。
这就是说,它是预期的行为inline
在一个专门的版本是在调用点使用的关键字。 我的建议是总是设法优化和测量在相同的基准测试你的代码。
你可能有兴趣在一个非常类似的线程这是为什么F#代码这么慢? 。
专业化型
如果没有inline
,你正在使用通用的比较,这是非常低效的。 与inline
,所述通用性是去除和int
比较直接使用。