Почему arg = args[n++] более эффективен, чем два отдельных оператора в более ранних компиляторах?

Из книги "Ядро Java для нетерпеливых", глава "Операторы увеличения и уменьшения"

String arg = args [n ++];

устанавливает arg в args[n], а затем увеличивает n. Это имело смысл тридцать лет назад, когда компиляторы не очень хорошо оптимизировали код. В настоящее время нет недостатка в производительности при использовании двух отдельных операторов, и многие программисты находят явную форму более удобной для чтения.

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

Какова была производительность при написании таких заявлений, как String arg = args[n++]?

3 ответа

Решение

С годами архитектура и компиляторы стали лучше. Учитывая улучшения в архитектуре процессоров и компиляторов, я бы сказал, что нет однозначного ответа на это.

С точки зрения архитектуры - многие процессоры поддерживают STORE & POINTER AUTO-INCREMENT как один цикл ЦП. Так и раньше - то, как вы написали код, будет влиять на результат (одна или несколько операций). В частности, архитектуры DSP были хороши при параллельном соединении (например, TSP DSP, такие как C54xx, с инструкциями и инструкциями после инкремента и после декремента, которые можно выполнять в кольцевых буферах - например, * "ADD * AR2 +, AR2–, A; после доступа к операндам)., AR2; увеличивается на единицу. " - из набора ссылок TSP TMS320C54x). Ядра ARM также содержат инструкции, которые допускают аналогичный параллелизм ( инструкции VLDR, VSTR - см. Документацию)

С точки зрения компилятора - Компилятор смотрит на то, как переменная используется в своей области (что не могло быть раньше). Он может видеть, используется ли переменная позже или нет. Может случиться так, что в коде переменная увеличивается, но затем отбрасывается. Какой смысл делать это? В настоящее время компилятор должен отслеживать использование переменных, и он может принимать разумные решения на основе этого (если вы посмотрите на Java 8 - компилятор должен иметь возможность определять "эффективно окончательные" переменные, которые не переназначаются).

Некоторые процессоры, такие как Motorola 68000, поддерживают режимы адресации, которые разыменовывают указатель, а затем увеличивают его. Например:

выдержка из справочного руководства программиста MC68000

Старые компиляторы могли бы использовать этот режим адресации для выражения типа *p++ или же arr[i++], но, возможно, не сможет распознать его в двух утверждениях.

Эти операторы обычно использовались программистами для удобства, а не для достижения производительности. Потому что эффективно, оператор будет разделен на две строки во время компиляции!! По-видимому, издержки на выполнение операторов Post/Pre-increment/decment были бы больше по сравнению с уже разделенным оператором с двумя строками!

Другие вопросы по тегам