Есть ли разница в производительности между inc (i) и i: = я + 1 в Delphi?

У меня есть процедура с большим количеством

i := i +1;

в нем, и я думаю

 inc(i);

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

EDIT: Я сделал некоторые измерения производительности и нашел разницу быть очень маленькой, на самом деле всего лишь 5.1222741794670901427682121946224e-8! Так что это действительно неважно. И варианты оптимизации действительно не сильно меняли результат. Спасибо за все советы и предложения!

Ответ 1

Современные компиляторы оптимизируют код.
inc (i) и i: = я + 1; почти одинаковы.

Используйте то, что вы предпочитаете.

Изменить: как Джим МакКит исправил: с проверкой переполнения есть разница. Inc не выполняет проверку диапазона.

Ответ 2

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

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

Ответ 3

Все зависит от типа "i". В Delphi обычно объявляются переменные loop как "i: Integer", но также может быть "i: PChar", который разрешает PAnsiChar на всем, что находится ниже Delphi 2009 и FPC (я предполагаю здесь), и PWideChar on Delphi 2009 и Delphi.NET(также гадают).

Так как Delphi 2009 может выполнять указатель-математику, Inc (i) также может быть выполнен на типизированных указателях (если они определены с включением POINTER_MATH).

Например:

type
  PSomeRecord = ^RSomeRecord;
  RSomeRecord = record
    Value1: Integer;
    Value2: Double;
  end;

var
  i: PSomeRecord; 

procedure Test;
begin
  Inc(i); // This line increases i with SizeOf(RSomeRecord) bytes, thanks to POINTER_MATH !
end;

Как уже говорили другие участники: легко решить, что компилятор сделал из вашего кода, открыв:

Виды > Отладка Windows > ЦП Windows > Разборка

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

Совет по этому вопросу: в каждом блоке $INCLUDE файл, который управляет параметрами компилятора, таким образом, вы не потеряете настройки, когда ваши .bdsproj или .dproj каким-то образом повреждены. (Посмотрите на исходный код JCL для хорошего примера)

Ответ 4

Вы можете проверить его в окне CPU во время отладки. Сгенерированные команды CPU одинаковы для обоих случаев.

Я согласен Inc(I); выглядит лучше, хотя это может быть субъективным.

Исправление: я только что нашел это в документации для Inc:

"На некоторых платформах Inc может генерировать оптимизированный код, особенно полезный в плотные петли".

Поэтому, вероятно, желательно придерживаться Inc.

Ответ 5

Вы всегда можете написать оба фрагмента кода (в отдельных процедурах), поместить контрольную точку в код и сравнить ассемблер в окне CPU.

В общем, я бы использовал inc (i) везде, где он, очевидно, использовался только как цикл/индекс какого-то типа, и + 1, где бы 1 не упрощал работу кода (т.е. другое целое число в будущем) или просто более читаемым с точки зрения алгоритма/спецификации.

Ответ 6

"На некоторых платформах Inc может генерировать оптимизированный код, особенно полезный в жестких циклах". Для оптимизированного компилятора, такого как Delphi, все равно. Речь идет о старых компиляторах (например, Turbo Pascal)