Bug 92217 - Innefficient pattern in equals() used
Summary: Innefficient pattern in equals() used
Status: VERIFIED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 3.1   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 3.1 M7   Edit
Assignee: Michael Van Meekeren CLA
QA Contact:
URL:
Whiteboard:
Keywords: performance
Depends on:
Blocks:
 
Reported: 2005-04-21 10:08 EDT by Michael Van Meekeren CLA
Modified: 2005-05-12 09:03 EDT (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Michael Van Meekeren CLA 2005-04-21 10:08:31 EDT
For consistancy and future developers not inheriting this code due to copy
paste, all equals methods that do not try to aggressively exit should be updated.

bad pattern:
        boolean equals = true;
        equals &= Util.equals(defined, someObject.defined);
        equals &= Util.equals(description, someObject.description);
        return equals;

changed to: 
        if (!Util.equals(defined, castedObject.defined))
		return false;
        if (!Util.equals(description, castedObject.description))
        	return false;
        return true;
Comment 1 Michael Van Meekeren CLA 2005-04-21 10:13:36 EDT
fixed HEAD
Comment 2 Douglas Pollock CLA 2005-04-21 12:19:49 EDT
I've just gone through and tweaked these a bit.  The code has the following pattern:

    if (!boolean)
        return false;
    return true;

Which I've changed to:

    return boolean;
Comment 3 Chris McLaren CLA 2005-05-07 14:21:41 EDT
Hi guys. You might also consider the following replacement as well, which
guarantees at least as good performance characteristics as the previously
suggested replacement:

return 
    Util.equals(defined, castedObject.defined) &&
    Util.equals(description, castedObject.description) &&
    Util.equals(id, castedObject.id) &&
    Util.equals(name, castedObject.name) &&
    Util.equals(parentId, castedObject.parentId);

Thanks to short-circuit evaluation (which is guaranteed by the language spec)
this expression will always aggressively exit on the first false term. And it
saves a bunch of ifs, nots, and returns in the code.

The pattern I originally used wasn't intentionally designed to look n00b. The
problem was the bitwise-and assignment operator &=. Java does not have a
logical-and assignment operator, which if it did might look like this: &&=).
This was my oversight. The compiler was happily and without warning treating the
boolean r-value as an integer, and as a result was unable to optimize further.
Comment 4 Chris McLaren CLA 2005-05-07 14:54:24 EDT
Another small point for performance is that equals() would do nicely to check if
the instance is identical before bothering to compare fields for equality. The
general pattern for class X with fields f1,f2,f3 then becomes:

X.equals(Object object) {
    if (object == this)
        return true;
    if (!(object instanceof X))
        return false;
    X castedObject = (X) object;
    return 
        Util.equals(f1, castedObject.f1) &&
        Util.equals(f2, castedObject.f2) &&
        Util.equals(f3, castedObject.f3);
}
Comment 5 Douglas Pollock CLA 2005-05-09 13:59:43 EDT
Regarding comment #4: I had adopted this pattern in the
"org.eclipse.core.commands" package.  It may not be adopted universally through
all of the workbench.
Comment 6 Michael Van Meekeren CLA 2005-05-12 09:03:22 EDT
verified by checking a few classes I fixed on Version: 3.1.0
Build id: I20050509-2010