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

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

i := i +1;

в нем и я думаю

 inc(i);

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

РЕДАКТИРОВАТЬ: я провел некоторую оценку производительности и обнаружил, что разница очень мала, на самом деле всего лишь 5,1222741794670901427682121946224e-8! Так что это действительно не имеет значения. И варианты оптимизации действительно не сильно изменили результат. Спасибо за все советы и предложения!


person Niklas Winde    schedule 26.09.2008    source источник
comment
5.1222741794670901427682121946224e-8?? Что не так с 5.12e-8? :-) Я не могу придумать ни одного практического приложения, требующего 32 значащих цифры, ни какого-либо измерения, даже половина из которых верна. Математик хочет, чтобы число пи равнялось 1 миллиарду знаков, а инженеру число пи равно 3,14.   -  person stevenvh    schedule 15.02.2009
comment
Хе-хе, ну, я провел тест, и это был результат, поэтому я просто вырезал и вставил его, отсюда и большое количество цифр :)   -  person Niklas Winde    schedule 16.02.2009


Ответы (6)


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

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

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

person Burkhard    schedule 26.09.2008
comment
Неправильный! Включите проверку диапазона или проверку переполнения и посмотрите на разборку! - person Jim McKeeth; 27.09.2008

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

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

person Jim McKeeth    schedule 27.09.2008
comment
Это кажется неправдой. Inc() выполняет проверку переполнения, когда эта опция включена. Проверено в D2007 и XE8. Так что нет абсолютно никакой разницы между Inc(i) и i := i + 1. - person LU RD; 06.08.2015

Все зависит от типа «i». В Delphi переменные цикла обычно объявляются как «i: Integer», но это также может быть «i: PChar», который разрешается в PAnsiChar во всем, что ниже Delphi 2009 и FPC (я предполагаю здесь), и в PWideChar на 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 ЦП > Дизассемблирование

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

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

person Community    schedule 26.09.2008

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

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

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

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

Так что, вероятно, целесообразно придерживаться Inc.

person Ondrej Kelle    schedule 26.09.2008

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

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

person robsoft    schedule 26.09.2008

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

person Community    schedule 26.09.2008