pharo-vcs / iceberg

Iceberg is the main toolset for handling VCS in Pharo.
MIT License
134 stars 85 forks source link

`IceCommit >> isParentOf:` is much slower than it ought to be. #1835

Open mariari opened 3 months ago

mariari commented 3 months ago

I was programming some visual tooling to see which topics are parents of others and I noticed that IceCommit >> isParentOf: is much too slow. Thankfully there is a good way around this by using the repository above the given commit to call mergeBaseBetween:and: (I believe my use case was using IceLibgitRepository). This sped up the operation from failing to finish to working in 6 seconds.

Here is an example implementation of this technique from one of my classes

https://github.com/mariari/Misc-GT-Scripts/blob/master/src/MiscGTScripts/GitTopicInfo.class.st#L79

{ #category : #predicates }
GitTopicInfo >> isParentOf: anotherTopic [
    <argument: #anotherTopic isKindOf: #GitTopicInfo>
    <return: #Boolean>
    ^ self topic commit id
        = (self topic repository
                mergeBaseBetween: self topic commit id
                and: anotherTopic topic commit id)
]

Here topic returns a IceGitRemoteBranch, but any IceCommitish subclass should work for this implementation.

Basically we just compare the commit id of ourselves and check if that is the merge base. If it is, then great we are the parent!

There are better ways to do this, the merge base itself offers a --is-ancestor flag which would likely be even more efficient.

https://git-scm.com/docs/git-merge-base

Also another note on performance, when running this on 66 topics asking each other if they are the parent this is still not fully optimal, it seems to spend most of the time calling LGitExternalEnumerationUInt32 class>>fromInteger:. If this is from the return value to check the ancestor against, then this can be optimized out. below is the performance trace I had when I ran the naive n^2 algorithm checking parent relations.

https://pomf2.lain.la/f/z5fwopij.png