||>的性能影响;和|||> F#中的管道运营商

时间:2014-02-28 13:38:19

标签: performance f# functional-programming inline pipeline

这个问题基本上扩展到this question,答案是单个参数管道运算符|>被编译为与unpiped版本相同的CIL。但是||>|||>呢? MSDN建议使用真正的元组来包装参数。

但是||>|||>确实分配一个.NET Tuple来包装参数然后再打开它们只是将它们传递给一个函数或者是编译器优化到通过像|>一样重写CIL来处理这些运算符?

更新

感谢您的回答。这取决于--optimize+参数是否传递给F#编译器。

在Visual Studio 2013中使用F#3.1构建的默认版本不会创建元组。默认的调试版本会创建元组。

3 个答案:

答案 0 :(得分:4)

编辑:最初我在尝试时实际上混淆了优化和非优化组件,并认为它没有优化它;但实际上确实如此。

我实际上尝试过了。我尝试了以下模块:

module Library1

let f x y = (x, y) ||> (+)

然后用ILSpy反编译它。

在没有优化(--optimize-)的情况下进行编译时,它提供以下内容:

public static int f(int x, int y)
{
    Tuple<int, int> tuple = new Tuple<int, int>(x, y);
    int item = tuple.Item1;
    int item2 = tuple.Item2;
    return item + item2;
}

使用优化(--optimize+)进行编译时,它提供以下内容:

public static int f(int x, int y)
{
    return x + y;
}

所以,是的,优化会删除元组创建。

答案 1 :(得分:3)

是的,在可能的情况下,编译器将像|>一样优化运算符。

正如一个有趣的例子,编译器将优化此代码

let add a b = a + b
let test() = (1,2) ||> add

到这个

3

即使你参数化了test

let test t = t ||> add

它会编译成这个C#等价物

int test(int x, int y) { return x + y; }

在真实的,更复杂的代码中,您可能看不到这种极端优化,但它让您了解编译器可以做什么。

答案 2 :(得分:3)

大多数F#运算符都声明为inline,这意味着它们基本上可以在优化器发挥作用之前通过文本替换来工作。供参考,以下是源代码

||>的定义
let inline (||>) (x1,x2) f = f x1 x2

如果将其与|>

进行比较
let inline (|>) a b = b a

我期待类似的优化