Подтвердить что ты не робот

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

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

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

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

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

Изменить: Я не могу заставить его, так что я могу его обнаружить?

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

Ответ 3

Существует новый способ поощрения более агрессивной встраивания в .net 4.5, описанной здесь: http://blogs.microsoft.co.il/blogs/sasha/archive/2012/01/20/aggressive-inlining-in-the-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; 
    } 
}

Ответ 4

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

Google поднял это:

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

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

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

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

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

Ответ 5

Нет, вы не можете.

В принципе, вы не можете сделать это в большинстве современных компиляторов С++. inline - это просто предложение компилятору. Он может принять это или нет.

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

Ответ 6

почему бы не использовать небезопасный код (встроенный c как его известный) и использовать указатели стиля c/С++, это безопасно от GC (т.е. не затрагивается коллекцией), но имеет свои собственные последствия для безопасности (can not use for internet зонные приложения), но отлично подходит для того, что, по-видимому, вы пытаетесь достичь, особенно с производительностью, и тем более с массивами и побитовыми операциями?

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

EDIT: немного стартера? http://msdn.microsoft.com/en-us/library/aa288474(VS.71).aspx

Ответ 7

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

Ответ 8

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

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

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

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

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

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

Ответ 9

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

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

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

JIT Enhancements в .NET 3.5 SP1