Могу ли я проверить, встроил ли компилятор C # вызов метода?

StackOverflow https://stackoverflow.com/questions/616779

Вопрос

Я пишу игру XNA, в которой я проверяю коллизии по пикселям.Цикл, который проверяет это, делает это путем сдвига int и побитового ORing и, как правило, сложен для чтения и понимания.

Я хотел бы добавить частные методы, такие как private bool IsTransparent(int pixelColorValue) чтобы сделать цикл более читаемым, но я не хочу накладных расходов на вызовы методов, поскольку это очень чувствительный к производительности код.

Есть ли способ заставить компилятор встроить этот вызов или я просто надеюсь, что компилятор выполнит эту оптимизацию?

Если нет способа принудительно выполнить это, есть ли способ проверить, был ли метод встроен, за исключением чтения дизассемблирования?Будет ли метод отображаться в reflection, если он был встроен и других вызывающих не существует?

Редактировать: Я не могу заставить это сделать, так могу ли я это обнаружить?

Это было полезно?

Решение

Нет, ты не можешь. Более того, тот, кто принимает решение о встраивании, не VS-компилятор, который берет ваш код и преобразует его в IL, а JIT-компилятор, который принимает IL и преобразует его в машинный код. Это связано с тем, что только JIT-компилятор знает достаточно об архитектуре процессора, чтобы решить, является ли целесообразным размещение метода inline, поскольку это компромисс между конвейеризацией команд и размером кэша.

Так что даже поиск в .NET Reflector вам не поможет.

Другие советы

  

" Вы можете проверить   System.Reflection.MethodBase.GetCurrentMethod (). Имя.   Если метод встроен, он будет   вернуть имя звонящего   вместо & Quot;.

- Джоэл Коухорн

Существует новый способ поощрения более агрессивного встраивания в .net 4.5, который описан здесь: http://blogs.microsoft.co.il/blogs/sasha/archive/2012/01/20/aggressive -inlining-в-CLR-4-5-jit.aspx

По сути, это просто флаг, указывающий компилятору на включение, если это возможно. К сожалению, он не доступен в текущей версии XNA (Game Studio 4.0), но должен быть доступен, когда XNA догонит VS 2012 в этом году. Он уже доступен, если вы каким-то образом работаете на Mono.

[MethodImpl(MethodImplOptions.AggressiveInlining)] 
public static int LargeMethod(int i, int j)
{ 
    if (i + 14 > j) 
    { 
        return i + j; 
    } 
    else if (j * 12 < i) 
    { 
        return 42 + i - j * 7; 
    } 
    else 
    { 
        return i % 14 - j; 
    } 
}

Имейте в виду, что XBox работает по-другому.

В Google появилось это:

"Встроенный метод, который уменьшает накладные расходы при вызове метода.JIT преобразует во встроенное то, что удовлетворяет следующим условиям.

  • Размер IL-кода составляет 16 байт или меньше.
  • Команда перехода не используется (если предложение и т.д.).
  • Локальная переменная не используется.
  • Обработка исключений не была выполнена (try, catch и т.д.).
  • float не используется в качестве аргумента или возвращаемого значения метода (возможно, с помощью Xbox 360, не применяется).
  • Когда в методе есть два или более аргументов , он использует для поворота объявленный.

Однако виртуальная функция не преобразуется в встроенную."

http://xnafever.blogspot.com/2008/07/inline-method-by-xna-on-xbox360.html

Я понятия не имею, прав ли он.Кто-нибудь?

Нет, ты не можешь.

По сути, этого нельзя сделать в большинстве современных компиляторов C ++. inline - это просто предложение для компилятора. Это бесплатно или нет.

Компилятор C # не делает никаких специальных вставок на уровне IL. Оптимизатор JIT это то, что сделает это.

почему бы не использовать небезопасный код (как известно, встроенный c) и использовать указатели в стиле c / c ++, это безопасно от GC (то есть не зависит от коллекции), но имеет свои собственные последствия для безопасности (не может использоваться для Интернета приложений для зоны), но отлично подходит для тех вещей, которые, по-видимому, вы пытаетесь достичь, особенно с помощью производительности и, тем более, с массивами и побитовыми операциями?

Подводя итог, вы хотите производительность для небольшой части вашего приложения? использовать небезопасный код и использовать указатели и т. д., мне кажется, лучший вариант

РЕДАКТИРОВАТЬ: немного начала? http://msdn.microsoft.com/en-us /library/aa288474(VS.71).aspx

Единственный способ проверить это - получить или написать профилировщик и подключиться к событиям JIT. Вы также должны убедиться, что Inlining не отключена, как по умолчанию при профилировании.

Вы можете обнаружить его во время выполнения с помощью вышеупомянутого вызова GetCurrentMethod. Но это, похоже, пустая трата [1]. Самое простое, что можно сделать, - это просто ИДАДАСИТЬ MSIL и проверить там.

Обратите внимание, что это специально для компилятора , вставляющего вызов, и рассматривается в различных Reflection документы в MSDN.

  

Если метод, вызывающий метод GetCallingAssembly, расширяется встроенным компилятором (т. е. если компилятор вставляет тело функции в промежуточный язык Microsoft (MSIL), а не в вызов функции), то сборка возвращается методом GetCallingAssembly - это сборка, содержащая встроенный код. Это может отличаться от сборки, содержащей оригинальный метод. Чтобы гарантировать, что метод, вызывающий метод GetCallingAssembly, не будет встроен компилятором, вы можете применить атрибут MethodImplAttribute с MethodImplOptions.NoInlining.

Тем не менее, JITter также свободен для внутренних вызовов - но я думаю, что дизассемблер будет единственным способом проверить, что и что не делается на этом уровне.

Редактировать: просто чтобы устранить некоторую путаницу в этой теме, csc.exe будет встроенными вызовами MSIL - хотя JITter будет (вероятно) более агрессивным в этом.

[1] И, под отходами - я имею в виду, что (а) он побеждает цель встраивания (лучшую производительность) из-за поиска в Reflection. И (б), это, вероятно, изменит поведение встраивания, так что оно больше не будет встроенным. И, прежде чем думать, что вы можете просто включить его в сборках Debug с Assert или чем-то еще - поймите, что он не будет встроен во время Debug, но может быть в Release.

  

Есть ли способ заставить компилятор встроить этот вызов или я просто надеюсь, что компилятор выполнит эту оптимизацию?

Если встроить функцию дешевле, она будет. Так что не беспокойтесь об этом, если ваш профилировщик не скажет, что это действительно проблема.

Для получения дополнительной информации

Улучшения JIT в .NET 3.5 SP1

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top