Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve performance of Equals function in IndexPath #269

Conversation

alvaro-berruezo-unity3d
Copy link

What does the pull request do?

Improves the performance of the Equals function, as well as the == and != operations, by pre-calculating the hash code in the constructor and using it to compare the objects.

What is the current behavior?

When two IndexPath objects are compared for equality, the CompareTo method is executed, which can be too slow when comparing a large number of IndexPaths
The IndexPaths comparison is a limitation when trying to expand all nodes in a large tree, because it is a very heavily used operation used to convert model indexes to row indexes.

What is the updated/expected behavior with this PR?

In every constructor of the IndexPath we calculate the hash code and store it in a member. Then this member is used whenever we need to compare two IndexPath objects for equality, which is much faster than using the CompareTo method.

berruezo and others added 3 commits March 8, 2024 10:02
* _hashCode is an int, not a string
* CalculateHashCode is not overriding any method
* We can't use 'this' object before all of its fields are assigned, so CalculateHashCode must be static
Some tests were not passing because of two issues:
* The _hashCode value of the `default` IndexPath was 0, because it was not calculated in the constructor. This is wrong, it must have the same value as an empty IndexPath. To fix it, access the _hashCode by the GetHashCode method, and if it's 0, recalculate it.
* The hash code of an IndexPath with just an index was not the same as the one of an IndexPath with a path containing the same index value. We must subtract one to the index for them to be equal
Copy link
Collaborator

@danipen danipen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alvaro-berruezo-unity3d, I just have a question about your changes.

@@ -145,17 +155,22 @@ static IEnumerator<int> EnumerateSingleOrEmpty(int index)
}

public override int GetHashCode()
{
return _hashCode == 0 ? CalculateHashCode(_path, _index) : _hashCode;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this check here?

return _hashCode == 0 ? CalculateHashCode(_path, _index) : _hashCode;

I would expect to "just" return _hashCode since it's calculated in the constructor.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is for when the IndexPath is created as the default object (e.g. row.ModelIndex == default). In this case the hash code should be the same as the one in an empty IndexPath, but it's 0 because the constructor is not called

@danipen danipen requested a review from grokys March 8, 2024 11:52
@alvaro-berruezo-unity3d
Copy link
Author

The performance issue is already fixed by #273
Now the Equals function is not heavily used when expanding rows, so we can discard this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants