views:

619

answers:

6

I have a procedure with a lot of

i := i +1;

in it and I think

 inc(i);

looks a lot better. Is there a performance difference or does the function call just get inlined by the compiler? I know this probably doesn't matter at all to my app, I'm just curious.

EDIT: I did some gauging of the performance and found the difference to be very small, in fact as small as 5.1222741794670901427682121946224e-8! So it really doesn't matter. And optimization options really didn't change the outcome much. Thanks for all tips and suggestions!

+6  A: 

Modern compilers optimize the code.
inc(i) and i:= i+1; are pretty much the same.

Use whichever you prefer.

Edit: As Jim McKeeth corrected: with Overflow Checking there is a difference. Inc does not do a range checking.

Burkhard
Wrong! Turn on Range Checking or Overflow checking and look at the disassembly!
Jim McKeeth
+2  A: 

You can verify it in the CPU window while debugging. The generated CPU instructions are the same for both cases.

I agree Inc(I); looks better although this may be subjective.

Correction: I just found this in the documentation for Inc:

"On some platforms, Inc may generate optimized code, especially useful in tight loops."

So it's probably advisable to stick to Inc.

TOndrej
Inc skips range checking
Jim McKeeth
+1  A: 

You could always write both pieces of code (in separate procedures), put a breakpoint in the code and compare the assembler in the CPU window.

In general, I'd use inc(i) wherever it's obviously being used only as a loop/index of some sort, and + 1 wherever the 1 would make the code easier to maintain (ie, it might conceivable change to another integer in the future) or just more readable from an algorithm/spec point of view.

robsoft
isn't inc(i,1) just as clear and easy to change to inc(i,2)?
Argalatyr
A: 

"On some platforms, Inc may generate optimized code, especially useful in tight loops." For optimized compiler such as Delphi it doesn't care. That is about old compilers (e.g. Turbo Pascal)

+4  A: 

It all depends on the type of "i". In Delphi, one normally declares loop-variables as "i: Integer", but it could as well be "i: PChar" which resolves to PAnsiChar on everything below Delphi 2009 and FPC (I'm guessing here), and to PWideChar on Delphi 2009 and Delphi.NET (also guessing).

Since Delphi 2009 can do pointer-math, Inc(i) can also be done on typed-pointers (if they are defined with POINTER_MATH turned on).

For example:

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;

As the other anwsers already said : It's relativly easy to see what the compiler made of your code by opening up :

Views > Debug Windows > CPU Windows > Disassembly

Note, that compiler options like OPTIMIZATION, OVERFLOW_CHECKS and RANGE_CHECKS might influence the final result, so you should take care to have the settings according to your preference.

A tip on this : In every unit, $INCLUDE a file that steers the compiler options, this way, you won't loose settings when your .bdsproj or .dproj is somehow damaged. (Look at the sourcecode of the JCL for a good example on this)

PatrickvL
+9  A: 

There is a huge difference if Overflow Checking is turned on. Basically Inc does not do overflow checking. Do as was suggested and use the disassembly window to see the difference when you have those compiler options turned on (it is different for each).

If those options are turned off, then there is no difference. Rule of thumb, use Inc when you don't care about a range checking failure (since you won't get an exception!).

Jim McKeeth