How to prevent the JIT compiler from optimizing this method

I have an extension method that looks like this:

//[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; } } 

I use this method when parsing a file with BinaryReader to skip the space character block, among other things. I found that the JIT compiler optimizes it when I call it like this:

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

I tried adding the [MethodImpl (...)] attribute to instruct the JIT compiler not to optimize the method, but it does not work. Now, obviously, I could write another implementation of this that manipulates the base position of the stream buffer, but out of curiosity I would like to know why this is so.

The only ways I found to prevent optimization are to use IEnumerable results (for example, by calling the .FirstOrDefault () method as above) or copying the code to the calling method. I tried to prevent the optimization of the calling methods using MethodImplAttribute, but this will not work. Oddly enough, optimization is completely disabled under the Debug assembly, so it should not occur in any situation. Does anyone know another way to prevent optimization?

+4
source share
1 answer

No, JIT does not optimize it. However, none of your codes will be executed - because you are ignoring the return value. Prior to the first call to MoveNext() none of the code in the iterator block is started. This has nothing to do with JIT, and it all depends on how iterator blocks work.

You can read my articles on iterator blocks ( basics , implementation details ) and Eric Lippert's โ€œpsychic debuggingโ€ blog post ( part 1 ; part 2 ).

Note that calling FirstOrDefault() will only read the first character. It sounds like you really want to consume the entire thread until the condition works โ€” this means using something like Count() , which will iterate over the entire returned sequence.

Alternatively - and preferably IMO - write an "active" method with a return type of void. If you are not interested in the return value of a method, this is a signal that it is probably not the ideal method to call. (This is not always the case, but usually it is.)

+8
source

Source: https://habr.com/ru/post/1341146/


All Articles