Почему автоматические свойства не встроены по умолчанию? - PullRequest
4 голосов
/ 05 марта 2012

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

Однако автоматические свойства (насколько я понимаю) не могут иметь никакой логики и просто возвращают или устанавливают значение базового поля.Насколько я знаю, автоматические свойства обрабатываются компилятором и JIT точно так же, как и любые другие методы. (Все нижеприведенное будет основываться на предположении, что вышеприведенный абзац правильный.)

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

// Automatic Properties Example
public Object MyObj { get; private set; }

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

Примечание: я понимаю, что прирост производительности, вероятно, будет незначительным, особенно если JIT, вероятно, все равно их встроит, если его использоватьДостаточно времени, но, как бы мало это ни было для усиления, кажется логичным, что такая, казалось бы, простая оптимизация будет введена независимо.

Ответы [ 3 ]

5 голосов
/ 05 марта 2012

РЕДАКТИРОВАТЬ: JIT-компилятор работает не так, как вы думаете, а потому, что вы, вероятно, не совсем понимаете, что я пытался передать выше. Я процитировал ваш комментарий ниже:

Это другой вопрос, но, насколько я понимаю, методы проверяются только на наличие inline-достоинства, если они вызываются достаточно много раз. Не говоря уже о том, что сама проверка является ударом по производительности. (Пусть размер удара по производительности пока не имеет значения.)

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

JIT-компилятор x86 (x64 и ia64 не обязательно используют одни и те же методы оптимизации) проверяет несколько вещей, чтобы определить, является ли метод подходящим кандидатом для встраивания, определенно не только в число раз, когда он вызывается. В статье перечисляются такие вещи, как, если встраивание сделает код меньше, если сайт вызова будет выполняться много раз (т.е. в цикле), и другие. Каждый метод оптимизируется сам по себе, поэтому метод может быть встроен в один вызывающий метод, но не в другой, как в примере цикла. Эта эвристика оптимизации доступна только для JIT, компилятор C # просто не знает: он производит IL, а не нативный код. Между ними огромная разница ; Размер нативного и IL-кода может быть совершенно другим.

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


Компилятор jit содержит самые простые свойства, включая автоматические. Вы можете прочитать больше о том, как JIT решает встроить вызовы методов в этом интересном сообщении в блоге .

Ну, компилятор C # вообще не содержит встроенных методов . Я предполагаю, что это так из-за того, как спроектирован CLR. Каждая сборка предназначена для переноски с машины на машину. Много раз вы можете изменить внутреннее поведение сборки .NET без необходимости перекомпиляции всего кода, это может быть просто заменой (по крайней мере, когда типы не изменились). Если код был встроен, он нарушает этот (отличный, imo) дизайн, и вы теряете этот блеск.

Давайте сначала поговорим о встраивании в C ++. (Полное раскрытие, я не использовал C ++ полный рабочий день, поэтому я могу быть расплывчатым, мои объяснения ржавыми или совершенно неверными! Я рассчитываю на моих поддерживающих SO, чтобы исправить и ругать меня)

Встроенное ключевое слово C ++ похоже на сообщение компилятору: «Эй, чувак, я бы хотел, чтобы вы встроили эту функцию, потому что я думаю, что она повысит производительность». Un к счастью, это только говорит компилятору, что вы предпочли бы его встроенный; он не говорит, что должен.

Возможно, раньше, когда компиляторы были менее оптимизированы, чем сейчас, компилятор чаще всего компилировал бы эту встроенную функцию. Однако с течением времени компиляторы становились все умнее, и авторы компиляторов обнаружили, что в большинстве случаев они лучше определяли, когда должна быть встроена функция, которой был разработчик. В тех немногих случаях, когда это не так, разработчики могут использовать ключевое слово seriouslybro_inlineme (официально называемое __forceinline в VC ++).

Теперь, почему авторы компилятора делают это? Ну, встраивание функции не всегда означает повышение производительности. Хотя это, безусловно, может, оно также может опустошить производительность ваших программ, если используется неправильно. Например, мы все знаем, что одним из побочных эффектов встраивания кода является увеличение размера кода или «синдром жирного кода» (отказ от ответственности: ненастоящий термин). Почему «синдром жирного кода» является проблемой? Если вы посмотрите на статью, на которую я ссылался выше, она объясняет, среди прочего, что память работает медленнее, и чем больше ваш код, тем меньше вероятность того, что он поместится в самый быстрый кэш процессора (L1). В конце концов он может уместиться только в памяти, а затем встраивание ничего не сделало. Однако компиляторы знают, когда могут возникнуть такие ситуации, и делают все возможное, чтобы предотвратить это.

Сложив это вместе с вашим вопросом, давайте посмотрим на это так: компилятор C # походит на код написания кода для компилятора JIT: JIT просто умнее (но не гениально). Он часто знает, когда вставка выиграет или повредит скорости выполнения. Компилятор "старшего разработчика" C # не имеет ни малейшего представления о том, как встраивание вызова метода может принести пользу выполнению вашего кода во время выполнения, поэтому это не так. Я предполагаю, что на самом деле это означает, что компилятор C # умный, потому что он оставляет работу по оптимизации тем, кто лучше ее, в данном случае JIT-компилятору.

4 голосов
/ 05 марта 2012

Однако автоматические свойства (насколько я понимаю) не могут иметь никакой логики и просто возвращают или устанавливают значение базового поля.Насколько я знаю, автоматические свойства обрабатываются компилятором и JIT точно так же, как и любые другие методы.

То, что автоматические свойства не могут иметь никакой логики, является подробностью реализации, никаких специальных знаний отот факт, что требуется для компиляции.На самом деле, как вы говорите, свойства auto компилируются в вызовы методов.

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

2 голосов
/ 05 марта 2012

Автоматические свойства - это просто методы - свойства get / set генерируются автоматически. В результате в IL нет ничего особенного для них. Компилятор C # сам по себе выполняет очень небольшое количество оптимизаций .

Что касается причин, по которым нельзя встроить - представьте, что ваш тип находится в отдельной сборке, поэтому вы можете свободно менять источник этой сборки, чтобы получить безумно сложную функцию get / set для свойства. В результате компилятор не может рассуждать о сложности кода get / set, когда он впервые видит ваше автоматическое свойство при создании новой сборки в зависимости от вашего типа.

Как вы уже отметили в своем вопросе - "особенно, когда JIT, вероятно, все равно их встроит" - методы этого свойства, вероятно, будут встроены во время JIT.

...