Действительно ли компилятор C# достаточно умен для оптимизации этого кода?

Проигнорируйте удобочитаемость кода в этом вопросе.

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

int maxResults = criteria.MaxResults;

if (maxResults > 0)
{
    while (accounts.Count > maxResults)
        accounts.RemoveAt(maxResults);
}

или как это:

if (criteria.MaxResults > 0)
{
    while (accounts.Count > criteria.MaxResults)
        accounts.RemoveAt(criteria.MaxResults);
}

?

Править: criteria a class, и MaxResults простое целочисленное свойство (т.е. public int MaxResults { get { return _maxResults; } }.

Делает обработку компилятора C# MaxResults как черный квадрат и оценивают его каждый раз? Или действительно ли достаточно умно выяснить, что у меня есть 3 вызова к тому же свойству без модификации того свойства между вызовами? Что, если MaxResults было поле?

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

(Примечание: я не интересуюсь слушанием аргумента 'микрооптимизации', который может быть допустимым в конкретном случае, который я отправил. Я был бы точно так же, как некоторая теория позади того, что продолжается или не продолжается.)

26
задан Jon Seigel 29 January 2010 в 14:41
поделиться

6 ответов

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

, которые сказали, что другие ответы, которые говорят, что «компилятор» не выполняет эту оптимизацию, потому что свойство может иметь побочные эффекты как правильно, так и неправильно. Проблема с вопросом (помимо фундаментальной проблемы, которую она просто нельзя ответить, не на самом деле попробовать его и измерять результат), заключается в том, что «компилятор» на самом деле является двумя компиляторами: компилятор C #, который компиляторы, который компиляторы, а также компиляторы JIT , который компилирует IL к машиностроительному коду.

Компилятор C # никогда не выполняет такую ​​оптимизацию; Как отмечалось, это требовалось бы, чтобы составить компилятор в код вызываемого кода и проверить, что результат вычисляется, не изменяется в течение срока службы кода Callee. Компилятор C # не делает этого.

Compiler Jit может. Нет причин, почему это не могло. У этого есть весь код, сидящий прямо там. Он полностью свободен встроенную Getter Hotel, и если Jitter определяет, что включенный имущество Getter возвращает значение, которое может быть кэшировано в реестре и повторно используется, то это бесплатно сделать это. (Если вы не хотите, чтобы это было сделано, потому что значение может быть изменено в другой поток, то у вас уже есть ошибка состояния гонки; исправить ошибку, прежде чем беспокоиться о производительности.)

На самом деле Встройте свойство Fetch, а затем enregister значение, я понятия не имею. Я знаю практически ничего о джиттере. Но это разрешено делать, если оно видит в форме. Если вам интересно, делает ли это так или нет, вы можете либо (1) спросить кого-то, кто находится в команде, который написал джиттером или (2) изучить JackiDe Code в отладчике.

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

  • Время выполнения

  • Размер исполняемого кода

  • Размер исполняемого кода - это имеет серьезное влияние на исполняемое время, потому что большой код занимает больше времени, увеличивает размер рабочего набора, ставит давление на кэширует процессор , ОЗУ и файл страницы. Небольшой медленный код часто находится в долгосрочной перспективе , чем большой быстрый код в важных метриках, таких как время запуска и кэш-память.

  • Распределение регистра - это также имеет серьезное влияние на время выполнения, особенно в архитектурах, таких как x86, которые имеют небольшое количество доступных регистров. Enregistering ценность для быстрого повторного использования может означать, что для других операций, которые нуждаются в оптимизации; Возможно, оптимизация этих операций вместо этого будет чистая победа.

  • И так далее. Это по-настоящему сложно очень быстро.

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

59
ответ дан 28 November 2019 в 06:16
поделиться

Если критерии - это тип класса, я сомневаюсь, что он будет оптимизирован, потому что другой поток всегда может изменить это значение в то же время. Для структуры Я не уверен, но ощущение моего кишечника состоит в том, что оно не будет оптимизировано, но я думаю, что это не будет иметь большую разницу в этом случае в этом случае в этом случае.

0
ответ дан 28 November 2019 в 06:16
поделиться

Если MaxResults является свойством, то нет, он не будет его оптимизировать, так как геттер может иметь сложную логику, скажем:

private int _maxResults;
public int MaxReuslts {
  get { return _maxResults++; }
  set { _maxResults = value; }
}

Посмотрим, как изменится поведение, если он будет встроен в строки вашего кода?

Если нет логики... любой из написанных Вами методов в порядке, это очень маленькая разница и все о том, насколько читабельно ВАМ (или Вашей команде)... именно Вы смотрите на это.

8
ответ дан 28 November 2019 в 06:16
поделиться

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

Эрик Липперт вполне указывает довольно правильно, что он много зависит от того, что вы подразумеваете под «компилятором». C # -> IL компилятор? Или IL -> Машинный код (JIT) компилятор? И он прав, чтобы указать, что JIT вполне может быть в состоянии оптимизировать свойство Getter, поскольку она имеет всю информацию (тогда как C # -> IL компилятор не обязательно). Это не изменит ситуацию с несколькими потоками, но тем не менее это хорошая точка.

6
ответ дан 28 November 2019 в 06:16
поделиться

Хранение IP-адресов является хорошей практикой для входа в систему и отслеживания, но я думаю, что только captcha остановит спам, грубые атаки и наводнения.

Рекаптча действительно является хорошим решением.

-121--2929492-

Это НЕ сработало в IE8 (еще не сработало в FF):

$("#selectList").append(new Option("option text", "value"));

Это сработало DID:

var o = new Option("option text", "value");
/// jquerify the DOM object 'o' so we can use the html method
$(o).html("option text");
$("#selectList").append(o);
-121--1776704-

почему бы не протестировать его?

просто настроить 2 приложения консоли, чтобы он выглядел 10 миллионов раз и сравнить результаты... не забудьте запустить их как правильно выпущенные приложения, которые были установлены правильно, или вы не можете гарантировать, что вы не просто запускаете msil.

На самом деле вы, вероятно, получите около 5 ответов, в которых говорится: «Вы не должны беспокоиться об оптимизации». они явно не пишут подпрограммы, которые должны быть как можно быстрее, прежде чем стать читаемыми (например, игры).

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

На самом деле ЕДИНСТВЕННЫЙ способ ответить на любой из этих вопросов заключается в том, что это часть кода, которая получит пользу от оптимизации. Тогда вы должны знать виды вещей, которые увеличивают время на выполнение. Действительно, мы, простые смертные, не можем сделать это априори и поэтому должны просто попробовать 2-3 различные версии кода, а затем проверить его.

2
ответ дан 28 November 2019 в 06:16
поделиться

Это НЕ сработало в IE8 (еще не сработало в FF):

$("#selectList").append(new Option("option text", "value"));

Это сработало:

var o = new Option("option text", "value");
/// jquerify the DOM object 'o' so we can use the html method
$(o).html("option text");
$("#selectList").append(o);
-121--1776704-

Попробуйте Adobe LiveCycle Designer
Это поставляется с Adobe Master Suit и имеет все возможности для ES. Он работает с инфраструктурой PKI и будет публиковать «сертифицированные» PDF-документы, подтверждающие подлинность для получателей. Лучше начать с того, что уже существует.

-121--2620584-

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

Обратите внимание, что фактическая оценка свойства может быть встроена компилятором JIT, что делает его эффективным и простым полем.

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

5
ответ дан 28 November 2019 в 06:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: