如何防止JIT编译器优化此方法

时间:2011-02-24 14:13:50

标签: c# .net optimization iterator jit

我有一个类似于以下内容的扩展方法:

//[MethodImpl(MethodImplOptions.NoOptimization)]
public static IEnumerable<char> TakeWhile(this BinaryReader reader, Func<int, bool> condition)
{
    while (condition(reader.PeekChar()))
    {
        char c = reader.ReadChar();
        yield return c;
    }
}

在使用BinaryReader解析文件时,我使用此方法来跳过空格字符块等等。我发现JIT编译器正在优化它,当我这样称呼它时:

// Skip white space
this.reader.TakeWhile(IsWhiteSpace);//.FirstOrDefault();

我尝试添加[MethodImpl(...)]属性来指示JIT编译器不要优化方法,但它不起作用。现在显然我可以编写另一个实现这个操作底层流缓冲区位置的实现,但出于好奇,我想知道为什么会这样。

我发现阻止优化的唯一方法是使用IEnumerable结果(例如 - 通过调用上面评论的.FirstOrDefault())或将代码复制到调用方法中。我已经尝试使用MethodImplAttribute阻止调用方法的优化,但这不起作用。奇怪的是,优化在Debug构建下完全关闭,所以它不应该在任何情况下发生。有没有人知道另一种阻止优化的方法?

1 个答案:

答案 0 :(得分:8)

不,JIT 不是优化它。但是,您的代码都不会被执行 - 因为您忽略了返回的值。在第一次调用MoveNext()之前,迭代器块中的代码都不会运行。这与JIT无关,而且与迭代器块的工作方式有关。

您可能想阅读关于迭代器块(basicsimplementation details)和Eric Lippert的“心理调试”博客文章(part 1; part 2)的文章。< / p>

请注意,调用FirstOrDefault()只会读取第一个字符。听起来你真的想要消耗整个流,直到条件失败 - 这意味着使用Count()之类的东西来迭代整个返回的序列。

或者 - 并且最好是IMO - 使用void返回类型编写“active”方法来执行此操作。如果你对一个方法的返回值不感兴趣,那就是一个信号,它可能不是一个理想的调用方法。 (那不是总是的情况,但通常是。)

相关问题