PDA

View Full Version : "is" versus "<> nil" on speed?



cronodragon
29-12-2006, 03:24 AM
I have several loops and brances in which I'm using "<> nil" to check if the object reference is valid or an end of linked list have been found. But, I know "is" works in the same way, and at the same time is makes a type check. I'm thinking on changing all my "<> nil" comparisons by "is". Is it a good idea, or does the operation spends more processor cycles??

By the way, Happy New Year to the PGD staff and members, just in case I don't post anything later :D

JernejL
29-12-2006, 09:56 AM
[quote="cronodragon"]I have several loops and brances in which I'm using "<> nil" to check if the object reference is valid or an end of ]

i'd say they are most likely both branched, so you should make a speedtest..

savage
29-12-2006, 12:12 PM
My understanding is that <> nil is faster due to it being a a simple pointer test, while is would incurr more RTTI calls.

As it has already been said, write a test app to be certain.

jasonf
29-12-2006, 12:15 PM
hmmm... I've been using

if not (obj = nil)

is this slower than if obj <> nil ?

VilleK
29-12-2006, 12:35 PM
Try compiling the code below and open the CPU window to inspect the generated assembly:

procedure TForm1.Button1Click(Sender: TObject);
var
p : tobject;
begin
p := nil;
if p is TForm then
Tag := 1;
if Assigned(p) then
Tag := 3;
if p<>nil then
Tag := 4;
if not (p = nil) then
Tag := 5;
end;

"is" generates a call to a function that tests the rtti-class.
The other variants generated identical code: a simple test and branch.

So "is" is slightly slower, the others are identical.

jasonf
29-12-2006, 12:48 PM
This is good to know. Cheers.

dmantione
29-12-2006, 12:55 PM
My understanding is that <> nil is faster due to it being a a simple pointer test, while is would incurr more RTTI calls.


The difference is subtle, but "is" is implemented by analysing the virtual method tables, not the runtime type information. So, if you want to avoid RTTI bloat, you can still safely use "is".

"Is" is certainly slower than a nil check.

dmantione
29-12-2006, 12:59 PM
hmmm... I've been using

if not (obj = nil)

is this slower than if obj <> nil ?

This is an easy optimization, most compilers will generate the same code for both, including FPC. However, especially in complex bollean expressions, it can be good forr eadibility to remove some parenthesis.

jasonf
29-12-2006, 01:26 PM
well, the
if not (obj = nil)
needs the parenthesis and won't work any other way because the compiler needs the expression being reveresed by the not to be evaluated to a boolean value and the only way that happens is by putting it in parenthesis.

in the same way as
if a>10 or a<5
doesn't work

but

if (a>10) or (a<5)
does.

not very easy to read, but required.

WILL
29-12-2006, 03:10 PM
Funny, I often find the parenthesis makes it easy for me to read the code. :)

cronodragon
29-12-2006, 03:26 PM
Hey, thanks for all the help. Now it's clear. :D

Traveler
29-12-2006, 05:30 PM
Funny, I often find the parenthesis makes it easy for me to read the code. :)

I have the exact same thing :)

savage
30-12-2006, 10:08 AM
The difference is subtle, but "is" is implemented by analysing the virtual method tables, not the runtime type information. So, if you want to avoid RTTI bloat, you can still safely use "is".

I have not looked under the hood, so could you clarify why is does a VMT look up when no methods are involved. is only checks if a class is of a certain type, which seems to be to be a RTTI issue rather than a VMT issue, but maybe I'm overlooking something here.

dmantione
30-12-2006, 02:07 PM
Every class created carries a pointer to its VMT in its data. Two classes are of the same type if their VMT index is equal. So, to implement "is", the VMT offset is read from the class instance, then compared to the vmt offset of the right hand side. Then the parent VMT is tested, and so on until we reach Tobject.

JSoftware
30-12-2006, 02:30 PM
If that's correct then you are going to check if the pointer is nil anyways before using the "is" operator. Else you risk a heavy AV

JernejL
30-12-2006, 02:32 PM
I haven't seen anywhere that a object reference is nil when it is not yet created / when it is deleted, altrough in delphi a lot of functions work with this assumption (such as freeandnil) it is not part of any pascal standard / guidelines, so the object <> nil would probably not be "proper" code to check if a object reference is valid or not altrough it "works" under delphi & FPC (and others).

alexione
30-12-2006, 03:47 PM
Oh, I would give $1 million to have those features in C++!!! I've started working for a small gamedev team, and they are using C++. Before this project, I couldn't even imagine what kind of hell can produce single uninitialized variable. God bless Delphe & FPC & all other languages which have automatic initialization to nil/0/false/... :)

JernejL
30-12-2006, 04:36 PM
Oh, I would give $1 million to have those features in C++!!! I've started working for a small gamedev team, and they are using C++. Before this project, I couldn't even imagine what kind of hell can produce single uninitialized variable. God bless Delphe & FPC & all other languages which have automatic initialization to nil/0/false/... :)

This is not a rule in delphi / fpc, but is done for object references / variables. however, for other normal (i know for local variables using native and other types such as records for sure), it is not initialized to zero.

cronodragon
30-12-2006, 09:52 PM
hmmm... I've been using

if not (obj = nil)

is this slower than if obj <> nil ?

This is an easy optimization, most compilers will generate the same code for both, including FPC. However, especially in complex bollean expressions, it can be good forr eadibility to remove some parenthesis.

Does it mean it is a better practice to place if's inside other if's, instead of using parenthesis? In example, this...


if a = b then
if b = c then WriteLn&#40;'a = c!!'&#41;;

... is better than...


if &#40;a = b&#41; and &#40;b = c&#41; then WriteLn&#40;'a = c!!'&#41;;

:D

dmantione
30-12-2006, 10:04 PM
Of course not, in this case the parentheses reduce the amount of code, and thus readability and speed. I never said they are evil :P

When I wrote that I was thinking of code like:


else if (rd.typ=stringdef) or
(ld.typ=stringdef) or
((is_pchar(rd) or is_chararray(rd) or is_char(rd) or is_open_chararray(rd) or
is_pwidechar(rd) or is_widechararray(rd) or is_widechar(rd) or is_open_widechararray(rd)) and
(is_pchar(ld) or is_chararray(ld) or is_char(ld) or is_open_chararray(ld) or
is_pwidechar(ld) or is_widechararray(ld) or is_widechar(ld) or is_open_widechararray(ld))) then


(citation from FPC source). When you are working with code like this the parentheses, especially if, while editing, they get wrong indentation or end up on the wrong line, it can become a time consuming puzzle to get your expression right.

VilleK
30-12-2006, 10:12 PM
If that's correct then you are going to check if the pointer is nil anyways before using the "is" operator. Else you risk a heavy AV
"is" includes a nil test and returns false in that case.

JSoftware
30-12-2006, 10:41 PM
If that's correct then you are going to check if the pointer is nil anyways before using the "is" operator. Else you risk a heavy AV
"is" includes a nil test and returns false in that case.
I don't think so. My application crashes when I try the is operator on an uninitialized pointer

edit: or atleast it did right before.. Now I can't reproduce it anymore

cronodragon
30-12-2006, 10:45 PM
If that's correct then you are going to check if the pointer is nil anyways before using the "is" operator. Else you risk a heavy AV
"is" includes a nil test and returns false in that case.
I don't think so. My application crashes when I try the is operator on an uninitialized pointer

But if the pointer is uninitialized "is" will try to examine an instance that is void :? That's why it is crashing. When you use "is" with a pointer to nil, you get False.

JernejL
30-12-2006, 10:45 PM
Since we are all showing up our geniously designed code with awesome pointer wrestling or typecasting, let me share some of mine :P


this calculates proper constant for sending wav raw wave data to openal:


format &#58;= AL_FORMAT_MONO8 + &#40;&#40;wavheader.BitsPerSample div 8&#41; - 1&#41; +
&#40;wavheader.NumChannels - 1&#41; * 2;


and a similar thing for opengl texture upload:


glTexImage2D&#40;GL_TEXTURE_2D, 0, 3 + integer&#40;&#40;format = GL_BGRA_EXT&#41; or &#40;format = GL_RGBA&#41;&#41;,
Width, Height, 0, format, GL_UNSIGNED_BYTE, pData&#41;;

JSoftware
31-12-2006, 12:00 AM
If that's correct then you are going to check if the pointer is nil anyways before using the "is" operator. Else you risk a heavy AV
"is" includes a nil test and returns false in that case.
I don't think so. My application crashes when I try the is operator on an uninitialized pointer

But if the pointer is uninitialized "is" will try to examine an instance that is void :? That's why it is crashing. When you use "is" with a pointer to nil, you get False.
My point exactly :wink:

Chebmaster
20-03-2007, 04:45 PM
Why nobody had mentioned the Assigned() function? It is what is intended to check if an object/pointer is not nil in Pascal, *not* the "is" operator.
Using "is" for that purpose is a big overkill. Its purpose is to check if the object A's class is equal to or descendant of the given class.

VilleK
20-03-2007, 10:07 PM
Why nobody had mentioned the Assigned() function?
But I do mention it in my first post :)

NecroDOME
21-03-2007, 10:28 AM
cool :), nice to know what is fastest :P ... for the if x<>nil then I mostly use if Assigned(x) then (however I THINK it's slower, but no sure...)

Mirage
22-03-2007, 06:41 AM
however I THINK it's slower, but no sure...

Assigned(x) is a pseudo-function and the compiler generates the same code for it as for x<>nil

NecroDOME
22-03-2007, 09:05 AM
no, it's different that x <> nil. I had some problems if I Assigned x and freed x, x was not nil! So I used if Assigned().

Mirage
22-03-2007, 09:55 AM
When you call SomeObject.Free SomeObject will not become nil. And if you call Assigned(SomeObject) it will return True because Assigned() just tests its argument for nil.
But there is FreeAndNil() - it frees object and sets it to nil.