C # оптимизации и побочные эффекты - PullRequest
5 голосов
/ 19 января 2011

Может ли оптимизация, выполняемая компилятором C # или JITter, иметь видимые побочные эффекты?

Один пример, который я отключил.

var x = new Something();
A(x);
B(x);

При вызове A(x) xгарантированно будет поддерживаться до конца A - потому что B использует тот же параметр.Но если B определено как

public void B(Something x) { }

, оптимизатор может исключить B(x), а затем может потребоваться вызов GC.KeepAlive(x).

Может ли эта оптимизация на самом деледолжно быть выполнено JITter?

Существуют ли другие оптимизации, которые могут иметь видимые побочные эффекты, кроме изменений трассировки стека?

Ответы [ 4 ]

8 голосов
/ 19 января 2011

Если ваша функция B не использует параметр x, то ее удаление и ранний сбор x не имеют видимых побочных эффектов.

Чтобы быть «видимыми побочными эффектами», они должны быть видимы для программы , а не для внешнего инструмента, такого как отладчик или средство просмотра объектов.

6 голосов
/ 19 января 2011

При вызове A (x) x гарантированно сохраняется до конца A - поскольку B использует тот же параметр.

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


Может ли эта оптимизация (а именно, выполнить раннюю очистку ссылки, которая нигде не используется) на самом деле JITter?

Да, и на практике это делается. Это не наблюдаемый побочный эффект.

Это оправдано разделом 3.9 спецификации, которую я привожу для вашего удобства:

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


Может ли оптимизация, выполняемая компилятором C # или JITter, иметь видимые побочные эффекты?

На ваш вопрос ответили в разделе 3.10 спецификации, которую я привожу здесь для вашего удобства:

Выполнение программы на C # продолжается так что побочные эффекты каждого выполняющийся поток сохраняется в критические точки выполнения.

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

Критическое исполнение точки, в которых порядок этих побочные эффекты должны быть сохранены ссылки на изменчивые поля, операторы блокировки, и создание и завершение потока.

Среда исполнения свободна для изменить порядок выполнения C # программа при условии соблюдения следующего ограничения:

Зависимость данных хранится в потоке выполнение. То есть ценность каждого переменная вычисляется так, как будто все операторы в потоке были выполнены в оригинальном программном порядке.

Правила порядка инициализации сохранились.

The порядок побочных эффектов сохраняется в отношении изменчивых чтений и пишет.

Кроме того, среда выполнения не должна оценивать часть выражения, если оно можно сделать вывод, что это выражение значение не используется и что не нужно побочные эффекты производятся (в том числе любой вызванный вызовом метода или доступ к изменчивому полю).

Когда выполнение программы прерывается асинхронное событие (например, исключение, выброшенное другим потоком), не гарантируется, что наблюдаемые побочные эффекты видны в оригинальная программа заказа.

От второго к последнему абзацу я считаю, что вас больше всего беспокоит; то есть, какую оптимизацию разрешено выполнять среде выполнения для воздействия на наблюдаемые побочные эффекты? Среде выполнения разрешено выполнять любую оптимизацию, которая не влияет на наблюдаемый побочный эффект.

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

Если это не отвечает на ваш вопрос, задайте более конкретный вопрос . В частности, потребуется тщательное и точное определение «наблюдаемого побочного эффекта», чтобы ответить на ваш вопрос более подробно, если вы не считаете приведенное выше определение соответствующим вашему определению «наблюдаемого побочного эффекта».

0 голосов
/ 19 января 2011

Эрик Липперт начал серию о рефакторинге, которая заставляет меня поверить, что компилятор C # и JITter стараются не вводить побочные эффекты. Часть 1 и Часть 2 в данный момент онлайн.

0 голосов
/ 19 января 2011

Включение B в ваш вопрос просто смущает вопрос.Учитывая этот код:

var x = new Something();
A(x);

Если предположить, что A(x) является управляемым кодом, то при вызове A(x) сохраняется ссылка на x, поэтому сборщик мусора не может собрать x до тех пор, пока A возвращается.Или, по крайней мере, до A это больше не нужно.Оптимизация, выполняемая JITer (отсутствующие ошибки), не приведет к преждевременному сбору x.

Вы должны определить, что вы подразумеваете под «видимыми побочными эффектами».Можно надеяться, что оптимизация JITer, по крайней мере, побочным эффектом сделает ваш код меньше или быстрее.Эти "видимые"?Или вы имеете в виду «нежелательно»?

...